题目实际上要求一组
(x,y)
满足
gcd(x,y+i)=ai+1,0≤i<k
首先可以找到 x 的范围,即
接下来考虑 y ,可以列出如下的式子
接下来只需要把得到的 x 和
#include<cstdio>
#include<algorithm>
using namespace std;
#define LL long long
const LL oo=1e17;
LL a[10010];
LL gcd(LL a,LL b)
{
return b?gcd(b,a%b):a;
}
LL mul(LL x,LL y)
{
double t=(double)x*y;
if (t>oo) return oo;
return x*y;
}
LL lcm(LL a,LL b)
{
return mul(a/gcd(a,b),b);
}
LL exgcd(LL a,LL b,LL &x,LL &y)
{
if (!b)
{
x=1;
y=0;
return a;
}
LL ret=exgcd(b,a%b,y,x);
y-=a/b*x;
return ret;
}
LL multi(LL base,LL k,LL mod)
{
if (k<0)
{
base=-base;
k=-k;
}
LL ret=0;
for (;k;k>>=1,base=(base+base)%mod)
if (k&1) ret=(ret+base)%mod;
return ret;
}
int main()
{
LL n,m,x=1,u,v,v1,w,y,t1,t2,g;
int k;
scanf("%I64d%I64d%d",&n,&m,&k);
for (int i=1;i<=k;i++) scanf("%I64d",&a[i]);
for (int i=1;i<=k;i++)
{
x=lcm(x,a[i]);
if (x>n)
{
printf("NO\n");
return 0;
}
}
u=0;
v=a[1];
for (int i=2;i<=k;i++)
{
g=exgcd(v,a[i],t1,t2);
w=-u-i+1;
if (w%g)
{
printf("NO\n");
return 0;
}
v1=v;
v=v/g*a[i];
u=multi(multi(w/g,t1,v),v1,v)+u;
u%=v;
}
y=(u+v)%v;
if (!y) y+=v;
if (y+k-1>m)
{
printf("NO\n");
return 0;
}
for (int i=1;i<=k;i++)
if (gcd(x,y+i-1)!=a[i])
{
printf("NO\n");
return 0;
}
printf("YES\n");
}