题目链接:
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;
}