CF338D GCD Table (数论+扩展中国剩余定理)

原题:http://codeforces.com/contest/338/problem/D

题解:基本题意:gcd(i,x+j-1)=a[j] (j\varepsilon [1,k])是否存在。可以设:

x+j-1\equiv a[j](mod a[j])

整理得:

x\equiv a[j]-j+1(mod a[j])

这样就可以用合并方程的方法求出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;
}

 

posted @ 2018-12-23 21:15  Exception2017  阅读(230)  评论(0编辑  收藏  举报