首页 > 代码库 > codeforces 338D GCD Table

codeforces 338D GCD Table

什么都不会只能学数论QAQ

英文原题不贴了

题意:

有一张N*M的表格,i行j列的元素是gcd(i,j)
读入一个长度为k,元素大小不超过10^12的序列a[1..k],问这个序列是否在表格的某一行中出现过

1<=N,M<=10^12
1<=k<=10^4

 

首先显然x=lcm(a[i])

然后(y+i-1)%a[i]==0

即y%[i]=1-n

然后就神奇地变成了中国剩余定理

求出x和y后判无解即可,情况比较多

首先如果x和y超过n,m的范围或<0显然不对

然后注意枚举i看gcd(x,y+i-1)是否等于a[i]

恩?好像也不多

注意因为这个表示直接定义好的并没有实质地给出来,所以n,m都可以把int爆了

所有的计算过程都需要longlong?

什么都不会只能学数论QAQ

代码:

技术分享
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 using namespace std;
 7 #define ll long long
 8 ll rd(){ll z=0,mk=1;  char ch=getchar();
 9     while(ch<0||ch>9){if(ch==-)mk=-1;  ch=getchar();}
10     while(ch>=0&&ch<=9){z=(z<<3)+(z<<1)+ch-0;  ch=getchar();}
11     return z*mk;
12 }
13 ll n,m,o;  ll mo[11000],a[11000];
14 ll exgcd(ll a,ll b,ll &x,ll &y){
15     if(!b){  x=1,y=0;  return a;}
16     ll d=exgcd(b,a%b,x,y);
17     ll tmp=x;  x=y,y=tmp-a/b*y;
18     return d;
19 }
20 ll chn(){
21     ll M=mo[1],A=a[1],k,y;
22     for(int i=2;i<=o;++i){
23         ll tmp=a[i]-A,d=exgcd(M,mo[i],k,y);
24         if(tmp%d)  return -1;
25         ll tm=mo[i]/d;
26         k=(k*tmp/d%tm+tm)%tm,A+=k*M,M=M*mo[i]/d,A=(A+M)%M;
27     }
28     return A;
29 }
30 int main(){freopen("ddd.in","r",stdin);
31     cin>>n>>m>>o;
32     for(int i=1;i<=o;++i)  mo[i]=rd(),a[i]=1-i;
33     int y=chn();
34     ll x=1,d;
35     for(int i=1;i<=o;++i){
36         d=exgcd(x,mo[i],d,d);
37         x=x*mo[i]/d;
38     }
39     if(!y)  y=x;
40     if(y<0 || y+o-1>m || x>n){  cout<<"NO"<<endl;  return 0;}
41     for(int i=1;i<=o;++i)if(exgcd(x,y+i-1,d,d)!=mo[i]){  cout<<"NO"<<endl;  return 0;}
42     cout<<"YES"<<endl;
43     return 0;
44 }
View Code

 

codeforces 338D GCD Table