【BZOJ 1407】[Noi2002]Savage ExGCD
我bitset+二分未遂后就来用ExGCD了,然而这道题的时间复杂度还真是玄学......
我们枚举m然后对每一对用ExGCD判解,我们只要满足在最小的一方死亡之前无解就可以了,对于怎么用,就是ax+by=c,在这里c是距离差,a是速度差,b是m,x是我们要的解,y随意。
时间复杂度O(m*n*n*log),然而这是标解..........
#include <cstdio> int prob[120][3],len,n,c[16],p[16],l[16],S; inline int Min(int x,int y){ return x<y?x:y; } inline int Max(int x,int y){ return x>y?x:y; } inline int GCD(int x,int y){ return x==0?y:GCD(y%x,x); } void ExGCD(int a,int &x,int b,int &y){ if(!b){ x=1,y=0; return; } ExGCD(b,x,a%b,y); int temp=x; x=y,y=temp-a/b*y; } int main(){ freopen("savage.in","r",stdin); freopen("savage.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d%d%d",&c[i],&p[i],&l[i]); for(int i=1;i<=n;i++){ for(int j=i+1;j<=n;j++){ prob[++len][0]=c[i]-c[j], prob[len][1]=p[j]-p[i], prob[len][2]=Min(l[i],l[j]); if(prob[len][1]<0) prob[len][1]*=-1,prob[len][0]*=-1; } S=Max(S,c[i]); } for(int m=S;m<=1000000;m++){ bool god=1; for(int i=1;i<=len;i++){ int gcd=GCD(prob[i][1],m); if(prob[i][0]%gcd==0){ int x,y; ExGCD(prob[i][1],x,m,y); x=x*prob[i][0]/gcd; int t=m/gcd; x=(x%t+t)%t; if(x<=prob[i][2]){ god=0; break; } } } if(god){ printf("%d",m); return 0; } } }
苟利国家生死以, 岂因祸福避趋之。