2012年8月15日 星期三

中國餘數定理

wiki


在中國古代著名數學著作《孫子算經》卷下第28题,叫做“物不知數”,原文如下:
有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二。问物几何?
即,一個整數除以三餘二,除以五餘三,除以七餘二,求這個整數。

克罗内克符号

为了便于表述,对任意的正整数\mathbf{i,j}用一个常用函数\zeta_{i,j}表示,称之为克罗内克符号(Kronecker).定义:
\zeta_{i,j} =\begin{cases} 1, \; i=j \\ 0, \; i \ne j \end{cases}
使用该符号,即可给出上述一般同餘方程组的求解过程,分两步完成
  • 对每个1 \le i \le k,先求出正整数b_i满足b_i \equiv \zeta_{i,j} \pmod {m_j},即所求的b_i满足条件:b_i \equiv 1 \pmod {m_i},但被每个m_j(i\ne j)整除。其求法如下:记r_i =m_{1} \cdots m_{i-1} m_{i+1} \cdots m_k,根据条件m_1 ,\cdots,m_k两两互素,可知r_im_i也互素,故存在整数c_id_i使得r_i c_i + m_i d_i=1.令b_i = r_i c_i,则对每个i \ne j,相对应的m_j显然整除b_i,并且b_i \equiv 1 \pmod {m_i}。由此表明b_i即为所求。
  • 对于前述所求的b_i,令x_0 = \sum_{i=1}^k a_ib_i,则x_0 \equiv a_i b_i \equiv a_i \pmod {m_i},这说明x_0为上述同餘方程组的一个解,从而所有的解可表示为x = x_0 + n \prod_{i=1}^k m_i,其中的n可以取遍所有的整数。


#include<stdio.h>
#define DBG 1

int w[3],b[3];
int extgcd(int a, int b, int & x, int & y){
    if (b == 0) { x=1; y=0; return a; }
    int d = extgcd(b, a % b, x, y);
    int t = x; x = y; y = t - a / b * y;
    return d;
}
int china(int k){
    int i, d, x, y, m, a = 0, n = 1;
    for (i = 0; i < k; i++) n *= w[i];
    for (i = 0; i < k; i++) {
        m = n / w[i];
        d = extgcd(w[i], m, x, y);
        a += (y * m * b[i]) % n;
        if(DBG)printf("a y m b %d %d %d %d\n",a,y,m,b[i]);
    }
    if (a > 0) return a;
    else return (a + n);
}
int main(){
    w[0]=3,w[1]=5,w[2]=7,b[0]=0,b[1]=3,b[2]=4;
    int ans = china(2);
    printf("ans: %d\n",ans);
}

沒有留言:

張貼留言