poj2891 Strange Way to Express Integers:http://poj.org/problem?id=2891
其实应该是这样的:
P=b1(mod a1); (P%a1=b1)
P =b2(mod a2);
P =b3(mod a3);
……
P =bn(mod an);
给出a,b 求P
解:
第一条:a1*x+b1= P
第二条:a2*y+b2= P
第一条减去第二条: a1*x - a2*y = b2-b1
设A=a1,B=-a2,K=b2-b1,得到了A*x+B*y=K 标准同余方程
利用exgcd就可得解
(实际调用exgcd的时候不理会a2前面的负号)
如果K%d!=0,无解
否则,X=[ (x* K/d)%(B/d)+(B/d) ]%(B/d)
(LCU表示最小公倍数)
P= a1*X+b1+ 若干倍的LCU(a1,a2)
(或者把Y=(K-AX)/B,再P=a2*Y+b2+ 若干倍的LCU(a1,a2))
所以新的b= a1*x+b1,新的a= LCU(a1,a2),
把新的b当成b1,新的a当成a1,再去和a3和b3结合,一直到最后结束,最后的b就是X
同余方程(拓展欧几里得算法):http://blog.csdn.net/qq_36038511/article/details/76887494
代码~~
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
void exgcd(LL a,LL b,LL &d,LL &x,LL &y)
{
if (a==0)
{
x=0;y=1;
d=b;
}
else
{
LL tx,ty;
exgcd(b%a,a,d,tx,ty);
x=ty-(b/a)*tx;
y=tx;
}
}
int main()
{
LL a,b,d,x,y,b1,b2,m1,m2,A,B,K;
int n;
while (scanf("%d",&n)!=EOF)
{
bool u=true;
scanf("%lld%lld",&m1,&b1);
for (int i=2;i<=n;i++)
{
scanf("%lld%lld",&m2,&b2);
A=m1;B=m2;K=b2-b1;
exgcd(A,B,d,x,y);
if (K%d!=0) u=false;
x=((x*(K/d)%(B/d))+(B/d))%(B/d);
b1=x*m1+b1;
m1=m1*m2/d;
}
if (u==false) printf("-1\n");
else printf("%lld\n",b1);
}
return 0;
}