CodeForces-338D GCD Table
Posted dsjkafdsaf
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CodeForces-338D GCD Table相关的知识,希望对你有一定的参考价值。
题目描述
一张\(n\times m\) 的表,第$i \(行第\)j 列$是。
\(GCD(i,j)\)你有一个长度为\(k\) 的数列\(A\),询问是否存在\(i,j\)。
满足对任意的\(l\),均有\(GCD(i,j+l-1)=a_l(1\leq l\leq k)\)。
Input
第一行有\(3\)个整数\(n,m,k\)。
第二行有\(k\)个整数表示数组\(A\)。
$ 1<=n,m<=10^121<=k<=10000 $
$ 1<=a_i<=10^12$
Output
若存在输出\(YES\),否则输出\(NO\)。
Sample Input
100 100 5
5 2 1 2 1
100 8 5
5 2 1 2 1
100 100 7
1 2 3 4 5 6 7
Sample Output
YES
NO
NO
题目中要求我们在表中找到数列\(A\)。
即:
\[
\begincases
GCD(i,j)=A_1 \GCD(i,j+1)=A_2 \...... \GCD(i,j+k-1)=A_k\\endcases
\]
由于\(GCD\)内外可以同时除掉一个数,所以我们同时除掉\(A_i\)。
有:
\[
\begincases
GCD(i/A_1,j/A_1)=1 \GCD(i/A_2,(j+1)/A_2)=1 \...... \GCD(i/A_k,(j+k-1)/A_k)=1\\endcases
\]
题目开始变得明朗了起来。
首先,我们发现\(i\)必定能整除所有的\(A_i\),即\(i\)一定是\(LCM(A)\)的倍数。
同时,我们又发现\(j/A_1\)为整数,\((j+1)/A_2\)为整数,即:
\[
\begincases
j=0\%A_1 \j+1=0\%A_2 \...... \j+k-1=0\%A_k\\endcases
\]
我们可以利用中国剩余定理解出\(j\)的解集。
我们发现\(j\)的解集一定是\(Ans+k*LCM(A)\)。
让我们再回到之前的解题中去。
\(i=t*LCM(A),j=Ans+k*LCM(A)\)。
让我们证明\(i\)取\(LCM(A)\)时最优:
\(j\)的解集和\(i\)并没有关系.
在上面的条件中,我们要求\(GCD(t*(LCM(A)/A_i),(j+i-1)/A_i)=1\).
我们发现若\(t\)不等于\(1\)时,在\(GCD\)中必定会多带入一个因子,这样的话会使\(GCD\)为\(1\)变的比较麻烦。
所以,我们取\(i=LCM(A)\)一定是最优的。
即然\(i\)已经取了\(LCM(A)\),那\(j\)自然是取\(Ans\)了,否则的话由会多了\(LCM(A)\)的项。
最后带入检验即可。
一个坑点:两个数相乘会炸long long,要用快速乘。
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define reg register
#define clr(a,b) memset(a,b,sizeof a)
#define Mod(x) (x>=mod)&&(x-=mod)
#define abs(a) ((a)<0?-(a):(a))
#define debug(x) cerr<<#x<<"="<<x<<endl;
#define debug2(x,y) cerr<<#x<<"="<<x<<" "<<#y<<"="<<y<<endl;
#define debug3(x,y,z) cerr<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl;
#define rep(a,b,c) for(reg int a=(b),a##_end_=(c); a<=a##_end_; ++a)
#define ret(a,b,c) for(reg int a=(b),a##_end_=(c); a<a##_end_; ++a)
#define drep(a,b,c) for(reg int a=(b),a##_end_=(c); a>=a##_end_; --a)
#define erep(i,G,x) for(int i=(G).Head[x]; i; i=(G).Nxt[i])
#pragma GCC optimize(2)
inline int Read(void)
int res=0,f=1;
char c;
while(c=getchar(),c<48||c>57)if(c=='-')f=0;
do res=(res<<3)+(res<<1)+(c^48);
while(c=getchar(),c>=48&&c<=57);
return f?res:-res;
template<class T>inline bool Min(T &a, T const&b)
return a>b?a=b,1:0;
template<class T>inline bool Max(T &a, T const&b)
return a<b?a=b,1:0;
const int N=1e4+5,M=305,mod1=97,mod2=3761599;
bool MOP1;
int n,k,m,mod[N],res[N];
bool MOP2;
int Exgcd(int a, int b, int &x, int &y)
if(!b)
x=1,y=0;
return a;
int g=Exgcd(b,a%b,y,x);
y-=a/b*x;
return g;
inline int Mul(int x,int y,int mod)
int res=0,f=0;
if(y<0)f=1,y=-y;
while(y)
if(y&1)res=(res+x)%mod;
x=x+x%mod,y>>=1;
return f?-res:res;
inline int Excrt(void)
int M=mod[1],ans=res[1],x,y;
rep(i,2,k)
int g=Exgcd(M,mod[i],x,y);
if((res[i]-ans)%g)return -1;
y=mod[i]/g;
x=Mul(x,(res[i]-ans)/g,y);
x=(x+y)%y;
ans=M*x+ans,M=M/g*mod[i],ans%=M;
int z=(ans%M+M)%M;
if(!z)z=M;
return z;
int vis[1000005];
inline void _main(void)
n=Read(),m=Read(),k=Read();
rep(i,1,k)mod[i]=Read(),res[i]=((1-i)%mod[i]+mod[i])%mod[i];
int LCM=1;
rep(i,1,k)
LCM=LCM/__gcd(LCM,mod[i])*mod[i];
if(LCM<0||LCM>n)return(void)puts("NO");
int Now=Excrt();
if(Now==-1)return(void)puts("NO");
if(Now+k-1>m)return(void)puts("NO");
rep(i,1,k)if(__gcd(Now+i-1,LCM)!=mod[i])return(void)puts("NO");
return(void)puts("YES");
signed main()
_main();
return 0;
以上是关于CodeForces-338D GCD Table的主要内容,如果未能解决你的问题,请参考以下文章
SPOJ4491. Primes in GCD Table(gcd(a,b)=d素数,(1<=a<=n,1<=b<=m))加强版