D. GCD Table(div1)
分析 : 难度2700分,没记错的话是在cf上独立完成的最难的一题,必须纪念。首先分析可得行的序号一定是lcm(a1 ~ ak) ,假设列的序号从为x+1 ~ x+k ,那么可以知道对于每一个i ,一定有 a[ i ]整除 x + i 。 可以得到一系列同余方程形似
x - i mod a[ i ] ,使用扩展中国剩余定理可以得到最小整数解 , 然后遍历 1~k 检验是否满足即可
code :
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 10004; ll a[maxn],b[maxn]; ll ksmul(ll a,ll b,ll mod) { ll ans=0; while(b) { if(b&1) ans=(ans+a)%mod; a=(a+a)%mod; b>>=1; } return ans; } ll GCD(ll a,ll b){return b==0?a:GCD(b,a%b);} ll LCM(ll a,ll b){return a*b/GCD(a,b);} void ex_gcd(ll a,ll b,ll &x,ll &y,ll &gcd) { if(b==0) { x=1,y=0,gcd=a; return; } ex_gcd(b,a%b,x,y,gcd); ll t=x; x=y,y=t-a/b*y; } ll EX_CRT(int n) { ll ans=b[1],M=a[1],x,y,c,gcd; for(int i=2;i<=n;i++) { c=(b[i]-ans%a[i]+a[i])%a[i]; ex_gcd(M,a[i],x,y,gcd); if(c%gcd) return -1; x=ksmul(x,c/gcd,a[i]/gcd); ans+=x*M; M*=a[i]/gcd; ans=(ans%M+M)%M; } return ans; } int main() { int k; ll n,m,lcm; scanf("%I64d%I64d%d",&n,&m,&k); scanf("%I64d",&a[1]); lcm=a[1]; b[1]=(-1+a[1])%a[1]; for(int i=2;i<=k;i++) { scanf("%I64d",&a[i]); lcm=LCM(lcm,a[i]); b[i]=(-i)%a[i]+a[i]; } if(lcm>n||lcm<1) { printf("NO"); return 0; } ll x=EX_CRT(k); if(x<0||x+k>m) { printf("NO"); return 0; } for(int i=1;i<=k;i++) if(GCD(lcm,x+i)!=a[i]) { printf("NO"); return 0; } printf("YES"); return 0; }