CF338D GCD Table (数论+扩展中国剩余定理)
原题:http://codeforces.com/contest/338/problem/D
题解:基本题意:是否存在。可以设:
整理得:
这样就可以用合并方程的方法求出x和lcm,而行数i就为lcm。检验答案是否正确就可以了。
注意:这道题数较大要用到快速乘。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=11000;
ll n,m,a[N];
int p,flag;
ll exgcd(ll a,ll b,ll &x,ll &y){
if(a==0){x=0;y=1;return b;}
ll d,tx,ty;
d=exgcd(b%a,a,tx,ty);
x=ty-(b/a)*tx;
y=tx;
return d;
}
ll gcd(ll a,ll b){
if(a==0) return b;
return gcd(b%a,a);
}
ll mul(ll a,ll b,ll M){//快速乘
ll ans=0;ll f=1;
if(a<0) f=-1*f,a=-a;
if(b<0) f=-1*f,b=-b;
while(b){
if(b&1) ans=(ans+a)%M;
a=(a+a)%M;b>>=1;
}
return ans*f;
}
int main(){
// freopen("b.in","r",stdin);
scanf("%lld%lld%d",&n,&m,&p);
for(int i=1;i<=p;i++) scanf("%lld",&a[i]);
ll m1,m2,b1,b2,d,x,y,k;
m1=a[1];b1=a[1];flag=0;
for(int i=2;i<=p;i++){
m2=a[i];b2=a[i]-i+1;k=b2-b1;
d=exgcd(m1,m2,x,y);
if(k%d) {flag=1;break;}
x=mul(x,k/d,m2/d);//快速乘
x=(x+(m2/d))%(m2/d);
b1=m1*x+b1;
m1=m1/d*m2;
}
if(b1==0) b1=m1;
if(m1>n) flag=1;
if(b1>m-p+1) flag=1;
for(int i=1;i<=p;i++)
if(gcd(b1+i-1,m1)!=a[i]){
flag=1;break;
}
if(flag) printf("NO\n");
else printf("YES\n");
return 0;
}