【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;
    }
  }
}

 

posted @ 2017-08-15 06:25  TS_Hugh  阅读(159)  评论(0编辑  收藏  举报