codeforces 338D GCD Table


D. GCD Table
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Consider a table G of size n × m such that G(i, j) = GCD(i, j) for all1 ≤ i ≤ n, 1 ≤ j ≤ m.GCD(a, b) is the greatest common divisor of numbersa andb.

You have a sequence of positive integer numbers a1, a2, ..., ak. We say that this sequence occurs in table G if it coincides with consecutive elements in some row, starting from some position. More formally, such numbers1 ≤ i ≤ n and1 ≤ j ≤ m - k + 1 should exist thatG(i, j + l - 1) = al for all1 ≤ l ≤ k.

Determine if the sequence a occurs in tableG.

Input

The first line contains three space-separated integers n, m and k (1 ≤ n, m ≤ 1012;1 ≤ k ≤ 10000). The second line containsk space-separated integers a1, a2, ..., ak (1 ≤ ai ≤ 1012).

Output

Print a single word "YES", if the given sequence occurs in tableG, otherwise print "NO".

Examples
Input
100 100 5
5 2 1 2 1
Output
YES
Input
100 8 5
5 2 1 2 1
Output
NO
Input
100 100 7
1 2 3 4 5 6 7
Output
NO
Note

Sample 1. The tenth row of table G starts from sequence {1, 2, 1, 2, 5, 2, 1, 2, 1, 10}. As you can see, elements from fifth to ninth coincide with sequencea.

Sample 2. This time the width of table G equals 8. Sequencea doesn't occur there.




【分析】

扩展中国剩余定理。


¡ 转化问题:


¡ gcd(x,y)=a0, gcd(x,y+1)=a1, gcd(x,y+2)=a2……


¡ y=-k(modak) 是原式有解的必要条件


¡ 代入 验证,若原始条件成立则 x,y 由中国 剩 余 定理可得 x=lcm({ ak }) y 有唯一解


¡ 为答案,否则问题无解。



¡ 易知 x 最小为 lcm({ak}) ,在此时根据中国剩余定理 y 有唯一解,但是这个解只保证了 ak|x,y ,并没有保证 ak=gcd(x,y) ,由于随着 x,y 增大若干倍会更加不满足,所以此时是最有可能有解的情况,代入验证即可。


【代码】

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define M(a) memset(a,0,sizeof a)
#define fo(i,j,k) for(ll i=j;i<=k;i++)
using namespace std;
const int mxn=10005;
ll n,m,k;
ll a[mxn],b[mxn],w[mxn];
inline ll gcd(ll x,ll y)
{
	return x%y==0?y:gcd(y,x%y);
}
inline void exgcd(ll aa,ll bb,ll &x,ll &y)
{
	if(!bb)
	{
		x=1,y=0;
		return;
	}
	exgcd(bb,aa%bb,y,x);
	y-=(aa/bb)*x;
}
inline ll inv(ll aa,ll bb)
{
	ll x,y;
	exgcd(aa,bb,x,y);
	return (x%bb+bb)%bb;
}
inline ll mul(ll aa,ll bb,ll mod)  //快速乘 
{
	ll ans=0;
	if(bb<0) aa=-aa,bb=-bb;
	while(bb)
	{
		if(bb&1) ans=(ans+aa)%mod;
		bb>>=1;aa=(aa+aa)%mod;
	}
	return ans;
}
inline bool judge()
{
	ll lcm=1,a1,a2,b1,b2,t,tmp=a[1];
	fo(i,1,k)
	{
		b[i]=1-i;
		t=gcd(lcm,a[i]); 
		lcm=lcm/t*a[i];
		if(lcm>n) return 0;
	}
	fo(i,2,k)
	{
		a1=a[i-1],a2=a[i],b1=b[i-1],b2=b[i];
		t=gcd(a1,a2);
		if((b2-b1)%t!=0) return 0;
		a[i]=a1/t*a2;
		b[i]=inv(a1/t,a2/t);
		b[i]=b[i];
		b[i]=mul(b[i],(b2-b1)/t,a2/t);
		b[i]=mul(b[i],a1,a[i]);
		b[i]=(b[i]+b1)%a[i];
		b[i]=(b[i]%a[i]+a[i])%a[i];
	}
	ll y=b[k];
	if(!y) y+=a[k];
	if(y+k-1>m) return 0;
	fo(j,y,y+k-1)
	  if(gcd(lcm,j)!=w[j-y+1]) return 0;
	return 1;
}
int main()
{
	scanf("%I64d%I64d%I64d",&n,&m,&k);
	fo(i,1,k) scanf("%I64d",&a[i]),w[i]=a[i];
	if(judge()) printf("YES\n");
	else printf("NO\n");
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值