BZOJ 1407[Noi2002]Savage ExGCD

Posted TS_Hugh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
    }
  }
}

 

以上是关于BZOJ 1407[Noi2002]Savage ExGCD的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1407 [Noi2002]Savage

bzoj1407: [Noi2002]Savage

BZOJ 1407[Noi2002]Savage ExGCD

bzoj1407 [Noi2002]Savage——扩展欧几里得

BZOJ1407 NOI 2002 荒岛野人Savage

bzoj 1407: [Noi2002]Savage扩展欧几里得+中国剩余定理