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;
} 
京公网安备 11010502036488号