ABC193E

dyj133446

2022-12-07 12:14:57

Solution

### 题目大意 [题目传送门](https://www.luogu.com.cn/problem/AT_abc193_e) 多组数据。一个人坐公交从 $A$ 站坐到 $B$ 站,公交车先用 $x$ 秒到 $B$ 站,然后在 $B$ 站停 $y$ 秒,再用 $x$ 秒到 $A$ 站,再在 $A$ 站停 $y$ 秒,如此循环往复。而这个人先睡眠 $p$ 秒,再醒来 $q$ 秒,如此循环往复。求这个人最早何时能在 $B$ 站下车,若永远不能,输出 $infinity$。 ### 题目分析 令公交车往返两地 $a$ 次,此人已循环过程 $b$ 次,公交车停在 $B$ 地 $m$ 秒,此人醒来 $n$ 秒下车,可得等式: $2a(x+y)+x+m=b(p+q)+p+n$ 经整理得: $2a(x+y)+(-b)(p+q)=(p+n)-(x+m)$ 于是我们想到**扩欧**。 先解方程 $2a(x+y)+(-b)(p+q)=\gcd(2(x+y),p+q)$ 令 $i=x+m,j=p+n$ 枚举 $i,j$,求出 $a$ 的最小正整数解,代入第一个式子求解,取最小值输出,时间复杂度 $O(yq+\log(\max(2(x+y),p+q))$。 ### AC代码 ```cpp #include<bits/stdc++.h> using namespace std; bool flag; long long t,x,y,p,q,d,a,b,minn=0x7fffffffffffffff; long long ans; void Exgcd(long long a,long long b,long long &x,long long &y) { if(!b) { d=a,x=1,y=0; return; } Exgcd(b,a%b,x,y); long long tx=x; x=y; y=tx-a/b*y; } int main() { cin>>t; for(int t1=1;t1<=t;t1++) { cin>>x>>y>>p>>q; minn=0x7fffffffffffffff; flag=0; Exgcd(2*(x+y),p+q,a,b); for(long long i=x;i<x+y;i++) { for(long long j=p;j<p+q;j++) { if((j-i)%d!=0)continue; flag=1; long long k=(j-i)/d; long long aa=a*k; aa=(aa%((p+q)/d)+((p+q)/d))%((p+q)/d); minn=min(minn,aa*2*(x+y)+i); } } if(!flag)cout<<"infinity"; else cout<<minn; cout<<'\n'; } return 0; } ``` ## 别慌,还有优化 我们可以直接枚举 $j-i$,算出最小的 $i$ 代入求最小值,时间复杂度 $O(y+q+\log(\max(2*(x+y),p+q))$。 代码: ```cpp #include<bits/stdc++.h> using namespace std; bool flag; long long t,x,p,d,a,b,minn=0x7fffffffffffffff; int y,q; long long ans; void Exgcd(long long a,long long b,long long &x,long long &y) { if(!b) { d=a,x=1,y=0; return; } Exgcd(b,a%b,x,y); long long tx=x; x=y; y=tx-a/b*y; } int main() { cin>>t; for(int t1=1;t1<=t;t1++) { cin>>x>>y>>p>>q; minn=0x7fffffffffffffff; flag=0; Exgcd(2*(x+y),p+q,a,b); for(long long i=p-(x+y-1);i<=p+q-1-x;i++) { if(i%d!=0)continue; flag=1; long long k=i/d; long long aa=a*k; aa=(aa%((p+q)/d)+((p+q)/d))%((p+q)/d); if(i>=p-x)minn=min(minn,aa*2*(x+y)+x); else minn=min(minn,aa*2*(x+y)+x+(p-x-i)); } if(!flag)cout<<"infinity"; else cout<<minn; cout<<'\n'; } return 0; } ```