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;
}