一次同余方程求解模板(中國剩余定理)


此博客轉載於網絡(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\n",r1);
    }
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM