什么都不会只能学数论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 }
时间: 2024-11-05 11:51:23