Link:https://www.lydsy.com/JudgeOnline/problem.php?id=1407
Solution:
由于此题里n的范围很小,因此可以直接从小到大枚举m(O(m*n^2))
那么问题转变为一个判定性问题:已知m,问所有野人在它们的有生之年里是否会出现冲突
由于O(m*n^2)的复杂度符合要求,枚举每一对(i,j)是否会发生冲突即可
可将问题转化为求次同余式中最小的x
\[(step_i-step_j)x\equiv pos_j-pos_i(\mod m)\]
接下来就是数论里的套路了:
ax≡b(mod c)可以转化为求ax+cy=b,我们可以用扩展欧几里得求出x,y值,同时顺便求出GCD。
设k=c/GCD(a,c),
那么方程ax≡b(mod c)的一个特解:x0=x*(b/GCD(a,c))%c。(如果b不是GCD(a,c)的倍数则无解)
并且它的GCD(a,c)个解分别为:xi=(x0+i*(k))%c,{i=0,1,2,.....GCD(a,c)-1}。
方程ax≡b(mod c)的最小解为:(x0%k+k)%k。
Code:
#include <bits/stdc++.h> using namespace std; const int MAXN=20; int n,c[MAXN],p[MAXN],l[MAXN]; int exgcd(int a,int b,int &x,int &y) { if(!b){x=1;y=0;return a;} int ret=exgcd(b,a%b,x,y),t=x; x=y;y=t-a/b*y;return ret; } bool check(int m) { for(int i=1;i<n;i++) for(int j=i+1;j<=n;j++) { int A=p[i]-p[j],B=c[j]-c[i],x,y,GCD=exgcd(A,m,x,y); if(B%GCD) continue; x=((x*B/GCD)%(m/GCD)+abs(m/GCD))%(m/GCD); if(x<=min(l[i],l[j])) return false; } return true; } int main() { cin >> n;int mx=0; for(int i=1;i<=n;i++) cin >> c[i] >> p[i] >> l[i],mx=max(mx,c[i]); for(int i=mx;i<=1e6;i++) if(check(i)) return cout << i,0; return 0; }