hdu 3579 Hello Kiki【中国剩余定理】(模数不要求互素)(模板题)

<题目链接>

题目大意:

给你一些模数和余数,让你求出满足这些要求的最小的数的值。

解题分析:

中国剩余定理(模数不一定互质)模板题

#include<stdio.h>
using namespace std;
#define  ll long long
 
ll  A[11],B[11];//B[i]为余数 
ll dg,ans;//dg为A[i]的最小公倍数    ans 为最小解 
void exgcd(ll a, ll b, ll &d, ll&x, ll &y)
{
    if (!b) {d=a; x=1; y=0;}
    else
    {
        exgcd(b, a%b, d, y, x);
        y-=x*(a/b);
    }
}
ll gcd(ll a, ll b)
{
    if (!b) return a;
    else gcd(b, a%b);
}

ll china(ll n)
{
    ll a,b,d,x,y,dm;
    ll c,c1,c2;
    a=A[0]; c1=B[0];
    for (int i=1; i<n; i++)
    {
        b=A[i]; c2=B[i];
        exgcd(a, b, d, x, y);
        dm=b/d;
        c=c2-c1;
        if (c%d) return -1;
        x=((x*c/d)%dm+dm)%dm;//x可能为负
        c1=a*x+c1;
        a=a*b/d;
    }
    
    //求最小公倍数 
    dg=a;//dg是最大公约数
    if (!c1)//考虑c1为0的情况
    {
        c1=1;
        for (int i=0; i<n; i++)
        {
            c1=c1*A[i]/gcd(c1, A[i]);
        }
        dg=c1;//此时dg为最小公倍数
    }
    return c1;//c1为最小的X
}

int main(){
    int t;
    scanf("%d",&t);
    int ncase=0;
    while(t--){
        int m;
        scanf("%d",&m); 
        
        for(int i=0;i<m;i++)
        scanf("%lld",&A[i]);
        for(int i=0;i<m;i++)
        scanf("%lld",&B[i]);
        ans=china(m);     //利用模板找到满足条件的最小值 
        printf("Case %d: %lld
",++ncase,ans);
    }
    return 0;
}

2018-08-20

原文地址:https://www.cnblogs.com/00isok/p/9507996.html