codeforces 338D GCD Table

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

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 numbers 1 ≤ i ≤ n and 1 ≤ j ≤ m - k + 1 should exist that G(i, j + l - 1) = al for all 1 ≤ l ≤ k.

Determine if the sequence a occurs in table G.

Input

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

Output

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

Example
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 sequence a.

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



题意:给你一个n*m的矩阵,然后再给你一个长度为k的序列,然后问你这个序列是否出现在n*m这个矩阵各个左边点的gcd序列中,举个样例:8 8 

m n 1  2  3  4  5  6  7  8      n代表横坐标;m代表纵坐标,然后下划线部分 

1  1  1  1  1  1  1  1  1      就是各个坐标点所对应的最大公约数;

2  1  2  1  2  1  2  1  2      如果给一个长度为4 序列为3 1 1 3这个序列

3  1  1  3  1  1  3  1  1      可以看出m=3时有一个序列在n(3...6)正好匹配,此时

4  1  2  1  4  1  2  1  4      输出YES,else输出NO;

5  1  1  1  1  5  1  1  1      注意:只有这个序列只与横行对比;

6  1  2  3  2  1  6  1  2      数据范围很大,用long long

7  1  1  1  1  1  1  7  1

8  1  2  1  4  1  2  1  8


这一题卡了快两天了,先学扩展欧几里得,再学中国剩余定理,然后又学扩展中国剩余定理;感觉好神奇啊,可是一做题还是一脸蒙蔽,还是参考大牛们的代码才写出来,如果只是给我思想,我感觉还得想一个星期,还是太菜了,虽然数论只有我自己在学,虽然很难,但是我还是很想学数学;

网上有模板,可以套用扩展欧几里得和中国剩余定理的模板,贴上代码;

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define ll long long
ll a[10005],b[10005];
ll n,m,k;

ll gcd(ll a,ll b)
{
	return b==0?a:gcd(b,a%b);
}

ll Extended_Euclid(ll a,ll b,ll &x,ll &y)
{
	ll d;
	if(!b)
	{
		d = a; x = 1; y = 0;
	}
	else
	{
		d = Extended_Euclid(b , a%b , x , y);
		ll x0 = x;
		x = y;
		y = x0-(a/b)*y;
	}
	return d;
}

ll Chinese_Remainder(ll *m,ll *a)
{
	ll lcm = 1 , X = m[1] , Y = a[1];
	for(int i = 1; i <= k; i++)
	lcm = lcm/gcd(lcm,m[i])*m[i];
	for(int i = 2; i <= k; i++)
	{
		ll A = X,B = m[i] , d , x , y , c = a[i]-Y;
		d = Extended_Euclid(A , B , x , y);
		if(c % d)
		return -1;
		ll mod = m[i]/d;
		ll K = ((x*c/d) % mod + mod) % mod;
		Y = X*K+Y;
		X = X*m[i]/d;
	}
	return Y==0 ? lcm:Y;
}

bool check()
{
	ll I = Chinese_Remainder(a , b),J;
	if(I > n || I <= 0) return false;
	for(int i = 1; i <= k; i++)
	b[i] = 1-i;
	J = Chinese_Remainder(a , b);
	if(J+k-1 > m || J <= 0) return false;
	for(int i = 1; i <= k; i++)
	if(gcd(I , J+i-1) != a[i]) return false;
	return true;
}

int main()
{
	scanf("%lld %lld %lld",&n,&m,&k);
	for(int i = 1; i <= k; i++)
	scanf("%lld",&a[i]);
	check() ? puts("YES") : puts("NO");	
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值