Codeforces_338_D

http://codeforces.com/problemset/problem/338/D

中国剩余定理的应用,思路是确定可能符合的最小行和最小列,然后判断是否符合。若不符合则后面的(最小的倍数)也不会符合。

寻找最小行和最小列就用了非互质中国剩余定理模版。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define LL long long
using namespace std;

LL n,m,k,a[10005] = {0},b[10005];

LL gcd(LL a,LL b)
{
    return b?gcd(b,a%b):a;
}

LL e_gcd(LL a,LL b,LL &x,LL &y)
{
    if(!b)
    {
        x = 1;
        y = 0;
        return a;
    }
    LL ans = e_gcd(b,a%b,x,y),temp = x;
    x = y;
    y = temp-a/b*y;
    return ans;
}



LL CRT(LL *a,LL *m) //方程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=e_gcd(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;
}

int main()
{
    scanf("%I64d%I64d%I64d",&n,&m,&k);
    for(int i = 1;i <= k;i++)   scanf("%I64d",&b[i]);
    LL x = CRT(a,b);
    if(x > n || x < 1)
    {
        printf("NO
");
        return 0;
    }
    for(int i = 1;i <= k;i++)   a[i] = 1-i;
    LL y = CRT(a,b);
    if(y+k-1 > m || y < 1)
    {
        printf("NO
");
        return 0;
    }
    for(int i = 1;i <= k;i++)
    {
        if(gcd(x,y+i-1) != b[i])
        {
            printf("NO
");
            return 0;
        }
    }
    printf("YES
");
    return 0;
}
原文地址:https://www.cnblogs.com/zhurb/p/5946169.html