【CF#338D】GCD Table

【题目描述】

有一张N,M<=10^12的表格,i行j列的元素是gcd(i,j)

读入一个长度不超过10^4,元素不超过10^12的序列a[1..k],问是否在某一行中出现过

【题解】

要保证gcd(x,y)=a[i],显然x=lcm(a[1],a[2]……a[k])

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

即y%a[1]=0

y%a[2]=-1

……

y%a[n]=-(n-1)

这就转化为了中国剩余定理

求出y之后,只需验证gcd(x,y+i-1)=a[i]即可

 1 /*************
 2   CF#338D
 3   by chty
 4   2016.11.3
 5 *************/
 6 #include<iostream>
 7 #include<cstdio>
 8 #include<cstdlib>
 9 #include<cstring>
10 #include<ctime>
11 #include<cmath>
12 #include<algorithm>
13 using namespace std;
14 typedef long long ll;
15 ll n,m1,K,A,M,ans,lcm(1),m[10010],a[10010];
16 inline ll read()
17 {
18     ll x=0,f=1;  char ch=getchar();
19     while(!isdigit(ch))  {if(ch=='-')  f=-1;  ch=getchar();}
20     while(isdigit(ch))  {x=x*10+ch-'0';  ch=getchar();}
21     return x*f;
22 }
23 ll gcd(ll a,ll b) {return !b?a:gcd(b,a%b);}
24 void exgcd(ll a,ll b,ll &g,ll &x,ll &y)
25 {
26     if(b==0)  {x=1; y=0; g=a; return;}
27     exgcd(b,a%b,g,x,y);
28     ll t=x;x=y;y=t-a/b*y;
29 }
30 ll China()
31 {
32     for(ll i=1;i<=K;i++)  a[i]=1-i;
33     A=a[1],M=m[1];
34     for(ll i=2;i<=K;i++)
35     {
36         ll k,y,da=a[i]-A,g;
37         exgcd(M,m[i],g,k,y);
38         if(da%g)  return -1;
39         ll t=m[i]/g;
40         k*=da/g;
41         k=(k%t+t)%t;
42         A+=k*M;
43         M=M*m[i]/g;
44         A=(A+M)%M;
45     }
46     return A;
47 }
48 bool check()
49 {
50     if(lcm>n)  return 0;
51     ll ans=China();
52     if(ans<0)  return 0;
53     if(ans==0)  ans=lcm;
54     if(ans+K-1>m1)  return 0;
55     for(ll i=1;i<=K;i++)  if(gcd(lcm,ans+i-1)!=m[i])  return 0;
56     return 1;
57 }
58 int main()
59 {
60     //freopen("cin.in","r",stdin);
61     //freopen("cout.out","w",stdout);
62     n=read();  m1=read();  K=read();
63     for(ll i=1;i<=K;i++)  m[i]=read();
64     for(ll i=1;i<=K;i++)
65     {
66         lcm=lcm/gcd(lcm,m[i])*m[i];
67         if(lcm>n) break;
68     }
69     check()?puts("YES"):puts("NO");
70     return 0;
71 }
原文地址:https://www.cnblogs.com/chty/p/6025535.html