結果
| 問題 | No.3397 Max Weighted Floor of Linear |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2025-12-04 04:57:25 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 377 ms / 2,000 ms |
| コード長 | 4,779 bytes |
| 記録 | |
| コンパイル時間 | 2,285 ms |
| コンパイル使用メモリ | 204,916 KB |
| 実行使用メモリ | 7,720 KB |
| 最終ジャッジ日時 | 2025-12-04 04:57:35 |
| 合計ジャッジ時間 | 9,776 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 23 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
struct Minmod{long long x,q,len;}; //[x,x+q,x+2*q,...,x+(len-1)*q] O(logm)の等差数列で済む.
vector<Minmod> MinofModLinear(long long a,long long b,long long m){ //min(a*x+b modM)を更新するxを返す.
assert(0 < m && m <= numeric_limits<int>::max()); //mod*modの計算が必要.
a %= m,b %= m,a += m,b += m;
a = a>=m?a-m:a,b = b>=m?b-m:b; //a,bをmodMに.
vector<Minmod> ret = {{0,1,1}}; //X=0だけ特別.
if(a == 0 || b == 0) return {{0,1,1}}; //a=0orb=0は当然x=0が最善.
if(a) a = m-a; // a<=-aとして考える -ax+bのminを求める.
long long X = 0,Y = b; //現在のx,y;
if(a <= Y){ //q=1を処理.
long long len = Y/a; Y %= a;
ret.at(0) = {X,1,len+1};
X += len;
}
long long p1 = 0,q1 = 1,p2 = 1,q2 = 0; //p1/q1<=a/m<=p2/q2.
long long n = a,d = m; //n/dに近いp/qを探していく aq(modM)<=Yが欲しい.
while(n){ //だいたいStern-Brocot木 aq-mp<=Yとして考える.
long long move = d/n; d %= n; //p2/q2を更新.
p2 += p1*move,q2 += q1*move;
if(d == 0) break;
move = n/d; n %= d;
if(move > 0){
long long np = p1+p2*move,nq = q1+q2*move; //次のp1/q1.
long long c1 = a*q1-m*p1,c2 = a*q2-m*p2,c3 = a*nq-m*np; //a/m>=p1/q1の変形 aq-mpになる.
while(c3 <= Y){ //np/nqで更新の場合.
long long t = max(0LL,(c1-Y+(-c2)-1)/(-c2)); //Yを超えないだけ進む.
if(c1+c2*t == 0) break; //a/mと一致した場合.
long long dx = q1+q2*t,dy = c1+c2*t; //dyの値が欲しいやつになる aq modm<=Y.
long long len = Y/dy; Y %= dy;
ret.push_back({X+dx,dx,len});
X += dx*len;
}
p1 = np,q1 = nq; //p1/q1を更新.
}
}
return ret;
}
vector<long long> MinofModLinear(long long N,long long M,long long a,long long b){ //0<=x<Nでmin(ax+b modM)を返す.
assert(0 < N && 0 < M && max(a,b) < M);
long long X = 0;
vector<long long> ret;
for(auto [x,q,len] : MinofModLinear(a,b,M)){
if(N <= x) break;
long long r = x+q*(len-1);
ret.push_back(x);
if(r < N){ret.push_back(r); continue;}
long long add = (N-1-x)/q;
ret.push_back(x+add*q);
}
return ret;
}
int main(){
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int T; cin >> T;
while(T--){
long long N,M,A,B,C,D; cin >> N >> M >> A >> B >> C >> D;
auto f = [&](long long x) -> long long {
assert(0 <= x && x < N);
return A*x+B*((C*x+D)/M);
};
//long long g = gcd(M,C);
//D = D/g*g;
//D /= g,C /= g,M /= g;
//
long long best = -1;
vector<long long> BestX;
if(false){
for(int i=0; i<N; i++){
long long now = f(i);
if(now > best) BestX = {i},best = now;
else if(now == best) BestX.push_back(i);
}
}
if(A <= 0 && B <= 0) cout << f(0) << "\n";
else if(A >= 0 && B >= 0) cout << f(N-1) << "\n";
else if(A >= 0 && B <= 0){
if(A+B >= 0) cout << f(N-1) << "\n";
else{
long long answer = 0,type = A*M+B*C;
D = M-1-D,C = (M-C)%M;
if(type >= 0){
D = (C*(N-1)+D)%M,C = (M-C)%M;
for(auto x : MinofModLinear(N,M,C,D)){
C = (M-C)%M,D = (D-C*(N-1)%M+M)%M;
D = M-1-D,C = (M-C)%M;
answer = max(answer,f(N-1-x));
D = M-1-D,C = (M-C)%M;
D = (C*(N-1)+D)%M,C = (M-C)%M;
}
}
else for(auto x : MinofModLinear(N,M,C,D)){
D = M-1-D,C = (M-C)%M;
answer = max(answer,f(x));
D = M-1-D,C = (M-C)%M;
}
cout << answer << "\n";
}
}
else{
if(A+B <= 0) cout << f(0) << "\n";
else{
long long answer = 0;
if(A*M+B*C >= 0){
D = (C*(N-1)+D)%M,C = (M-C)%M;
for(auto x : MinofModLinear(N,M,C,D)){
C = (M-C)%M,D = (D-C*(N-1)%M+M)%M;
answer = max(answer,f(N-1-x));
D = (C*(N-1)+D)%M,C = (M-C)%M;
}
}
else for(auto x : MinofModLinear(N,M,C,D)) answer = max(answer,f(x));
cout << answer << "\n";
}
}
}
}