简单的中国剩余定理练习。
首先行数一定是$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 <iostream> #include <queue> #include <map> #include <cstring> #include <string> #include <algorithm> #include <cmath> #include <cstdlib> #include <cstdio> #include <iomanip> #include <ctime> #include <bitset> #include <set> #include <vector> #include <complex> using namespace std; #define ll long long #define up(i,j,n) for(ll i=j;i<=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<<50; inline ll read(){ char ch=getchar();ll x=0,f=1; while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='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<0) 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; }