CF#338D. GCD Table

时间:2023-12-19 10:15:26

传送门

简单的中国剩余定理练习。

首先行数一定是$lcm$,然后只要确定最小的列数就能判定解合不合法了。

我们可以得到线性模方程组:

$y \equiv 0 \pmod{a_1}$

$y+1 \equiv 0 \pmod {a_2}$

$y+2 \equiv 0 \pmod {a_3}$

$...$

$y+n \equiv 0 \pmod {a_{n+1}}$

然后CRT搞出来一组解,暴力判判就OK了。

//CF338D
//by Cydiater
//2017.2.20
#include &ltiostream>
#include &ltqueue>
#include &ltmap>
#include &ltcstring>
#include &ltstring>
#include &ltalgorithm>
#include &ltcmath>
#include &ltcstdlib>
#include &ltcstdio>
#include &ltiomanip>
#include &ltctime>
#include &ltbitset>
#include &ltset>
#include &ltvector>
#include &ltcomplex>
using namespace std;
#define ll long long
#define up(i,j,n)	for(ll i=j;i&lt=n;i++)
#define down(i,j,n)	for(ll i=j;i>=n;i--)
#define cmax(a,b)	a=max(a,b)
#define cmin(a,b)	a=min(a,b)
const ll MAXN=1e5+5;
const ll oo=1LL&lt<50;
inline ll read(){
	char ch=getchar();ll x=0,f=1;
	while(ch>'9'||ch&lt'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch&lt='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
ll N,M,K,m[MAXN],lcm=1,a[MAXN],a1,m1;
namespace solution{
	ll gcd(ll a,ll b){return !b?a:gcd(b,a%b);}
	void exgcd(ll a,ll b,ll &x,ll &y){
		if(!b){x=1;y=0;return;}
		exgcd(b,a%b,y,x);
		y-=a/b*x;
	}
	void CRT(){
		a1=a[1];m1=m[1];
		up(i,2,K){
			ll a2=a[i],m2=m[i],x,y,d=gcd(m1,m2);
			if((a2-a1)%d){a1=oo;return;}
			exgcd(m1,m2,x,y);
			ll mod=m2/d;
			x=((x*((a2-a1)/d)%mod+mod)%mod+mod)%mod;
			a1+=x*m1;
			m1=m1*m2/d;
			a1=(a1+m1)%m1;
		}
	}
	void Prepare(){
		N=read();M=read();K=read();
		up(i,1,K){
			m[i]=read();a[i]=1-i;
			lcm=lcm/gcd(lcm,m[i])*m[i];
		}
	}
	void Solve(){
		if(lcm>N)puts("NO");
		else{
			CRT();
			if(a1+K-1>M||a1&lt0)	puts("NO");
			else{
				if(a1==0)a1=lcm;
				if(a1+K-1>M){
					puts("NO");
					return;
				}
				up(i,1,K)if(gcd(lcm,a1+i-1)!=m[i]){
					puts("NO");
					return;
				}
				puts("YES");
			}
		}
	}
}
int main(){
	//freopen("input.in","r",stdin);
	using namespace solution;
	Prepare();
	Solve();
	return 0;
}