[转]使用中国剩余定理中处理某些方程模数不互质的方法

原地址:http://hi.baidu.com/aekdycoin/blog/item/71d7a842b93f611b73f05da4.html  

 

给定方程
x = c1 (mod b1) ……………………(1)
x = c2(mod b2) ………………………(2)
(b1,b2)可以不为1
于是通过取mod 定义,我们得到

x = k1 * b1 + c1………………(3)
(3) 带入(2)
k1 * b1 + c1 = c2 (mod b2)…………(4)
化简
k1 * b1 = c2 - c1 (mod b2)…………(5)
于是可以解得到
令G = gcd(b1,b2),C = c2 - c1 (mod b2)
那么由(5)得到
k1 * b1 = W * b2 + C
---->>>>>
k1 * b1 / G = W * b2 / G + C / G
令C'  = C/G
k1 * b1 / G = W * b2 / G + C '
k1 * b1 / G = C' (mod b2 / G)
--->

{

关于(6)怎么得到的,我做一下解释。在这纠结了好长时间。

(k1*(b1/G)) % (b2/G) = C' %(b2/G);

k1%(b2/G) = C'%(b2/G) / (b1/G)%(b2/G);

k1%(b2/G) = (C' * Xb1) % (b2/G)  ; Xb1是b1的逆元

令K = C' * Xb1;

}


k1 = K (mod b2/G)………………(6)

那么有
k1 = k' * b2/G + K………………(7)
(7)带入(3)
x = k' * b2 * b1/G + K * b1 + c1………………(8)

x = K*b1 + c1 (mod b1 * b2/G)

证毕!

 

贴一下模板 POJ 2891 很典型的这种问题:

//合并到最后得到一个式子 x = c(mod b);所以要求的x就是c。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>

#define CL(arr, val)    memset(arr, val, sizeof(arr))
#define REP(i, n)       for((i) = 0; (i) < (n); ++(i))
#define FOR(i, l, h)    for((i) = (l); (i) <= (h); ++(i))
#define FORD(i, h, l)   for((i) = (h); (i) >= (l); --(i))
#define L(x)    (x) << 1
#define R(x)    (x) << 1 | 1
#define MID(l, r)   (l + r) >> 1
#define Min(x, y)   x < y ? x : y
#define Max(x, y)   x < y ? y : x
#define E(x)    (1 << (x))

typedef long long LL;
using namespace std;

LL gcd(LL a, LL b) {
    return b ? gcd(b, a%b) : a;
}

LL ext_gcd(LL a, LL b, LL& x, LL& y) {
    if(b == 0) {
        x = 1; y = 0;
        return a;
    }
    LL p = ext_gcd(b, a%b, x, y);
    LL tmp = x;
    x = y; y = tmp - (a/b)*y;
    return p;
}

LL inmod(LL a, LL n) {
    LL x, y;
    if(ext_gcd(a, n, x, y) != 1)    return -1;
    return (x%n + n)%n;
}

int mergef(LL b1, LL c1, LL b2, LL c2, LL& b, LL& c) {
    LL tb1 = b1, tb2 = b2;
    c = ((c2 - c1)%b2 + b2)%b2;
    LL G = gcd(b1, b2);
    if(c%G) return 0;
    c /= G;
    b1 /= G;
    b2 /= G;
    c *= inmod(b1, b2);
    c %= b2;
    c *= tb1;
    c += c1;
    b = tb1*tb2/G;
    c %= b;
    return 1;
}

int main() {
    //freopen("data.in", "r", stdin);

    int t, i;
    LL b1, c1, b2, c2, b, c;

    while(~scanf("%d", &t)) {
        bool flag = true;
        scanf("%lld%lld", &b1, &c1);
        if(c1 >= b1) flag = false;
        for(i = 1;  i < t; ++i) {
            scanf("%lld%lld", &b2, &c2);
            if(c2 >= b2) flag = false;
            if(!flag)   continue;
            if(mergef(b1, c1, b2, c2, b, c) == 0)    flag = false;
            //printf("(%d %d), (%d %d), (%d %d)\n", b1, c1, b2, c2, b, c);
            b1 = b; c1 = c;
        }
        if(flag)    printf("%lld\n", c);
        else    printf("-1\n");
    }
    return 0;
}
posted @ 2012-06-16 09:36  AC_Von  阅读(1343)  评论(0编辑  收藏  举报