【题解】
可以枚举m
那么任意两个野人之间有 c[i]+x*p[i]=c[j]+x*p[j] (mod m) 无解,或 x 的最小值<=min(l[i] , l[j])
化为丢番图方程:(p[i]-p[j])*x+m*y=c[j]-c[i]
用扩展欧几里得搞就行了。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<ctime> 7 #include<algorithm> 8 using namespace std; 9 int n,mx,C[20],p[20],l[20]; 10 inline int read() 11 { 12 int x=0,f=1; char ch=getchar(); 13 while(!isdigit(ch)) {if(ch=='-') f=-1; ch=getchar();} 14 while(isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();} 15 return x*f; 16 } 17 int gcd(int a,int b) {return b==0?a:gcd(b,a%b);} 18 void exgcd(int a,int b,int &x,int &y) 19 { 20 if(b==0) {x=1; y=0; return;} 21 exgcd(b,a%b,x,y); 22 int t=x;x=y;y=t-a/b*y; 23 } 24 bool check(int m) 25 { 26 for(int i=1;i<=n;i++) 27 for(int j=i+1;j<=n;j++) 28 { 29 int a=p[i]-p[j],b=m,c=C[j]-C[i],x,y; 30 int r=gcd(a,b); 31 if(c%r==0) 32 { 33 a/=r; b/=r; c/=r; 34 exgcd(a,b,x,y); 35 b=abs(b); 36 x=((x*c)%b+b)%b; 37 while(!x) x+=b; 38 if(x<=min(l[i],l[j])) return 0; 39 } 40 } 41 return 1; 42 } 43 int main() 44 { 45 //freopen("cin.in","r",stdin); 46 //freopen("cout.out","w",stdout); 47 n=read(); 48 for(int i=1;i<=n;i++){C[i]=read(); p[i]=read(); l[i]=read(); mx=max(mx,C[i]);} 49 for(int i=mx;;i++) if(check(i)) {printf("%d ",i); break;} 50 return 0; 51 }