bzoj1407 [Noi2002]Savage——扩展欧几里得
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1407
看到一定有解,而且小于10^6,所以可以枚举;
判断一个解是否可行,就两两判断野人 i , j 能否满足在寿命内不相遇;
也就是 T*pi + ci ≡ T*pj + cj (mod m)
变成 ( pi - pj )*T + km = cj - ci
用扩展欧几里得解这个方程,得到T若大于两人中较小的寿命或无解则可行。
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std; int n,m,c[20],p[20],l[20]; int gcd(int a,int b){return (a%b==0)?b:gcd(b,a%b);} void exgcd(int a,int b,int &x,int &y) { if(b==0) { x=1; y=0; return; } exgcd(b,a%b,x,y); int t=x; x=y; y=t-(a/b)*y; } bool ck(int m) { for(int i=1;i<n;i++) for(int j=i+1;j<=n;j++) { int a=p[i]-p[j],b=m,cc=c[j]-c[i]; int g=gcd(a,b); // if(cc%g)return 0; if(cc%g)continue;//无解也满足 a/=g; b/=g; cc/=g; int x,y; // b=abs(b); if(b<0)b=-b; exgcd(a,b,x,y); x=((x*cc)%b+b)%b;//先%b! // x=(x*cc+b)%b; if(x<=min(l[i],l[j]))return 0; } return 1; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d%d%d",&c[i],&p[i],&l[i]),m=max(m,c[i]); for(int i=m;i<=1e6;i++) if(ck(i)) { printf("%d",i); return 0; } }