首页 > 其他 > 详细

HDU3579 Hello Kiki【一元线性同余方程组】

时间:2015-03-17 23:46:31      阅读:542      评论:0      收藏:0      [点我收藏+]

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=3579


题目大意:

Kiki有X个硬币,她用不同的方式数了N次,每次她把硬币分成大小相等的组,记录每次一组硬币

的个数Mi和数完最后剩余的硬币数Ai。那么问题来了:总共有多少枚硬币?


思路:

典型的一元线性同余方程组X = Ai(mod Mi)求解。题目要求输出最小正整数解,则如果求得同余

方程组的解为0,那么答案就是所有Mi的最小公倍数。


AC代码:

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

LL GCD(LL a,LL b)
{
    if(b == 0)
        return a;
    return GCD(b,a%b);
}

void ExGCD(LL a,LL b,LL &d, LL &x,LL &y)
{
    if( !b )
    {
        x = 1;
        y = 0;
        d = a;
    }
    else
    {
        ExGCD(b,a%b,d,y,x);
        y -= x * (a/b);
    }
}

LL A[15],R[15];

int main()
{
    LL a,b,c,d,x0,y0,lcm;
    int N,M,kase = 0;
    scanf("%d",&N);
    while(N--)
    {
        lcm = 1;
        bool flag = 1;
        scanf("%d",&M);
        for(int i = 1; i <= M; ++i)
        {
            scanf("%I64d",&A[i]);
            lcm = lcm / GCD(A[i],lcm) * A[i];
        }

        for(int i = 1; i <= M; ++i)
            scanf("%I64d",&R[i]);

        printf("Case %d: ",++kase);

        for(int i = 2; i <= M; ++i)
        {
            a = A[1];
            b = A[i];
            c = R[i] - R[1];
            ExGCD(a,b,d,x0,y0);
            if( c%d != 0 )
            {
                flag = 0;
                break;
            }
            LL temp = b/d;
            x0 = (x0*(c/d)%temp + temp) % temp;
            R[1] = A[1]*x0 + R[1];
            A[1] = A[1]*(A[i]/d);
        }
        if( !flag )
            printf("-1\n");
        else
        {
            if(R[1] != 0)
                printf("%I64d\n",R[1]);
            else
                printf("%I64d\n",lcm);
        }

    }

    return 0;
}



HDU3579 Hello Kiki【一元线性同余方程组】

原文:http://blog.csdn.net/lianai911/article/details/44352973

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!