Codeforces 338D GCD Table 题解&代码

来自中国剩余定理的恶意
我其实什么都不知道…直接看题解

思路:
我们需要得到的是一个(x,y)组
其中x满足x%a[i]=0,y满足y%a[i]=1-i(对于所有a[]),这样就可以保证x是a[i]的最小公倍数且y+i-1是所有a[i]的倍数(同条件下得到的将是最小的y)
然后检验一下x和y是不是满足gcd(x,y+i-1)=ai…不满足说明我们求出的x和y是无效的,既然已得到的x和y无效,那么x的倍数与y的倍数必然无效——无效的原因一定是gcd(x,y+i-1)>ai【x是a[i]的倍数,y+i-1是a[i]的倍数】
**对了,中国剩余定理是抄模板的

#include
#include
#define LL long long
using namespace std;
const int maxn=10005;
LL n,m,a[maxn],b[maxn];
int k;
LL gcd(LL a,LL b)
{
    if(!b)return a;
    return gcd(b,a%b);
}
LL exgcd(LL a,LL b,LL &x,LL &y)
{
    if(!b)
    {
        x=1,y=0;
        return a;
    }
    LL r=exgcd(b,a%b,x,y),x0=x;
    x=y;
    y=x0-(a/b)*y;
    return r;
}
LL china(LL *m,LL *a) //方程x%m=a;
{
    LL lcm=1,X=m[1],Y=a[1];
    for(int i=1;i<=k;i++)lcm=lcm/gcd(lcm,m[i])*m[i];
    for(int i=2;i<=k;i++)
    {
    LL A=X,B=m[i],d,x,y,c=a[i]-Y;
    d=exgcd(A,B,x,y);
    if(c%d)return -1;
    LL mod=m[i]/d;
    LL K=((x*c/d)%mod+mod)%mod;
    Y=X*K+Y;
    X=X*m[i]/d;
    }
    if(Y==0)return lcm;
    return Y;
}
bool check(void)
{
    LL I=china(a,b),J;
    if(I>n || I<=0)return false;
    for(int i=1;i<=k;i++)b[i]=1-i;
    J=china(a,b);
    if(J+k-1>m || J<=0)return false;
    for(int i=1;i<=k;i++)if(gcd(I,J+i-1)!=a[i])return false;
    return true;
}
int main(void)
{
    cin>>n>>m>>k;
    for(int i=1;i<=k;i++)
        cin>>a[i];
    if(check())cout<<"YES"<else cout<<"NO"<return 0;
}

你可能感兴趣的:(codeforces,中国剩余定理)