问题
就是让你求解同余方程
前言
如果所有的模数互质,那么是可以用中国剩余定理求解的,并且代码特别的段
但是如果不互质的话,如果你要用中国剩余定理来解的话就显得没这么方便了,因为你在求那个类似逆元的东西不好求,并且暴力求的话时间也不允许
所以就需要一个更优秀的东西来解
解法
我们观察两个同余方程
x≡a1(modm1)x≡a1(modm1)
x≡a2(modm2)x≡a2(modm2)
其实这个可以写成以下形式
x−y1∗m1=a1x−y1∗m1=a1
x−y2∗m2=a2x−y2∗m2=a2
两个式子相减可以得到
y1∗m1−y2∗m2=a2−a1y1∗m1−y2∗m2=a2−a1
然后这里m1,m2,(a2−a1)m1,m2,(a2−a1)都是已知的
所以我们可以当一个不定方程来解
这样的话就是我们可以解出一个y1y1
待回去就可以得到一个可能的x0x0
但是这个x0x0并不是合法的
他仅仅满足下面这个式子x=x0+k∗lcm(m1,m2)x=x0+k∗lcm(m1,m2)
这个的话又可以看成一个新的同余方程
x≡x0(mod[m1,m2])x≡x0(mod[m1,m2])
然后如果满足这个方程就可以满足那两个方程了
然后就成功地吧两个方程合为一个
然后一直合下去
就可以得到一个唯一的不定方程
这个的话直接用扩展欧几里得来解就可以了
CODE:
#include<cstdio>
typedef long long LL;
LL exgcd (LL a,LL b,LL &x,LL &y)
{
if (a==0)
{
x=0;y=1;
return b;
}
LL tx,ty;
LL d=exgcd(b%a,a,tx,ty);
x=ty-(b/a)*tx;
y=tx;
return d;
}
int main()
{
LL n;
LL b1,m1;
bool tf=true;
scanf("%lld",&n);
scanf("%lld%lld",&b1,&m1);
for (LL u=2;u<=n;u++)
{
LL b2,m2;
scanf("%lld%lld",&b2,&m2);
LL A,B,x,y,dd=b2-b1;
A=m1,B=m2;
LL d=exgcd(A,B,x,y);
if (dd%d!=0) {printf("no solution!");return 0;}
x=(x*(dd/d)%(B/d)+(B/d))%(B/d);
b1=m1*x+b1;
m1=m1*m2/d;
}
if (tf==false) printf("no solution!");
else printf("%lld\n",b1);
return 0;
}