此博客转载于网络(http://www.cnblogs.com/lmlyzxiao/p/4931129.html)
一次同余方程的求解步骤
1:求gcd(a,m)
2:令d = gcd(a,m) 如果d不能整除b则无解,否则转3
3:根据ex_gcd 求得一个解x0;
用扩展欧几里得求解的具体做法如下:
(1):用ex_gcd求得满足 ax' + my' = d 的x'和y'。具体方法是将 ax'+my' = d 变形可以得到 ax' = d - my';
对变形后的式子两边同时取模m得 ax'Ξd(mod)m,至此可见x'是同余方程的解
(2):根据x'求x0。具体方法是:由于d能整除b 设 p = b/d,则根据同余式的性质得到:a(px')≡dp(mod)m即:a(px')≡b(mod)m.因此x0 = px' = b/d*x'(mod)m.
4:根据求得的x0可以得到其他d-1个解为 xi = (x0 + i*m/d)(mod)m, i = 1,2,...d-1.
然后根据上面的方法去解上面的题。代码是求得方程组小于m的非负整数解。
#include <cstdio> #include <cstring> #include <iostream> #include <stack> #include <queue> #include <map> #include <algorithm> #include <vector> using namespace std; const int maxn = 1000005; typedef long long LL; LL ex_gcd(LL a,LL b,LL &x,LL &y) { if(b == 0){ x = 1; y = 0; return a; } LL r = ex_gcd(b,a%b,x,y); LL t = x; x = y; y = t - a/b*y; return r; } int main() { LL i,n,a1,r1,a2,r2,ans,a,b,c,d,x0,y0; while(scanf("%lld",&n)!=EOF){ bool flag = 1; scanf("%lld%lld",&a1,&r1); for( i=1;i<n;i++){ scanf("%lld%lld",&a2,&r2); a = a1; b = a2; c = r2-r1; LL d = ex_gcd(a,b,x0,y0); if(c%d!=0){ flag = 0; } int t = b/d; x0 = (x0*(c/d)%t+t)%t;//保证x0为正 r1 = a1*x0 + r1; a1 = a1*(a2/d); } if(!flag){ puts("-1"); continue; } printf("%lld ",r1); } return 0; }