同余方程组的扩展欧几里得解法
同余方程组
mod.in/.out/.cpp
【问题描述】
求关于 x 的同余方程组
x%a 1 =b 1
x%a 2 =b 2
x%a 3 =b 3
x%a 4 =b 4
的大于等于 0 的最小整数解。
【输入格式】
一行 8 个整数,表示a 1 ,b 1 ,a 2 ,b 2 ,a 3 ,b 3 ,a 4 ,b 4 a1,b1,a2,b2,a3,b3,a4,b4 。
【输出格式】
一行一个整数,答案除以 p 的余数。
【样例输入】
2 0 3 1 5 0 7 3
【样例输出】
10
【数据规模和约定】
对于 30% 的数据,a i ai ≤ 40, 保证 a i ai 均为素数。
对于 60% 的数据,1≤a i ≤10 3 1≤ai≤103 , 保证a i ai 均互素。
对于 100% 的数据,0≤b i <a i ,1≤a i ≤10 3 0≤bi<ai,1≤ai≤103 。
【限制】
时间:1S
内存: 256M
数据前六十膜数互素,可以用CRT求解
不互素怎么办?用扩展欧几里得
x%a 1 =b 1
x%a 2 =b 2
x%a 3 =b 3
x%a 4 =b 4
显然可以变成
k1*a1+b1=x
k2*a2+b2=x
....
的形式
那么 k1*a1+b1=k2*a2+b2移项 => a1*k1-a2*k2=b1-b2
woc这不是ax+by=m么
因为a,b并不互素,显然该式在(a,b)即(a1,a2)不整除m的时候是无解的
此时可用扩展欧几里得求出一组特解x
通解是
X=x+k*lcm(a1,a2)
由上式可知 X%lcm(a1,a2)=x,两个方程由此合并
令 M=lcm(a1,a2) R=b2-b1
合并后的方程为 X mod M = R
那么合并n个方程就是按顺序来合并啦!即M=lcm(a1,a2,a3.....)
那么上代码 其中数组m表示a,数组r表示b
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define LL long long LL a[6],r[6]; int n; LL exgcd(LL a,LL b,LL &x,LL &y) { if(b==0) {x=1,y=0;return a;} LL tmp=exgcd(b,a%b,y,x); y-=a/b*x; return tmp; } LL solve() { LL M=a[1],R=r[1],x,y,d; for(int i=2;i<=4;i++) { d=exgcd(M,a[i],x,y); if((R-r[i])%d!=0) return -1; x=(R-r[i])/d*x%a[i]; R-=x*M; M=M/d*a[i]; R%=M; } return (R%M+M)%M; } int main() { for(int i=1; i<=4; i++) scanf("%lld%lld",&a[i],&r[i]); printf("%lld\n",solve()); return 0; }