Codeforces_338_D
http://codeforces.com/problemset/problem/338/D
中国剩余定理的应用,思路是确定可能符合的最小行和最小列,然后判断是否符合。若不符合则后面的(最小的倍数)也不会符合。
寻找最小行和最小列就用了非互质中国剩余定理模版。
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #define LL long long using namespace std; LL n,m,k,a[10005] = {0},b[10005]; LL gcd(LL a,LL b) { return b?gcd(b,a%b):a; } LL e_gcd(LL a,LL b,LL &x,LL &y) { if(!b) { x = 1; y = 0; return a; } LL ans = e_gcd(b,a%b,x,y),temp = x; x = y; y = temp-a/b*y; return ans; } LL CRT(LL *a,LL *m) //方程x%m=a; { LL lcm=1,X=m[1],Y=a[1]; for(int i=1;i<=k;i++) lcm=lcm/gcd(lcm,m[i])*m[i]; for(int i=2;i<=k;i++) { LL A=X,B=m[i],d,x,y,c=a[i]-Y; d=e_gcd(A,B,x,y); if(c%d)return -1; LL mod=m[i]/d; LL K=((x*c/d)%mod+mod)%mod; Y=X*K+Y; X=X*m[i]/d; } if(Y==0) return lcm; return Y; } int main() { scanf("%I64d%I64d%I64d",&n,&m,&k); for(int i = 1;i <= k;i++) scanf("%I64d",&b[i]); LL x = CRT(a,b); if(x > n || x < 1) { printf("NO\n"); return 0; } for(int i = 1;i <= k;i++) a[i] = 1-i; LL y = CRT(a,b); if(y+k-1 > m || y < 1) { printf("NO\n"); return 0; } for(int i = 1;i <= k;i++) { if(gcd(x,y+i-1) != b[i]) { printf("NO\n"); return 0; } } printf("YES\n"); return 0; }