zoukankan      html  css  js  c++  java
  • 个人理解---中国剩余定理

                  a1 r1    a2  r2     a3 r3 
    有一个数x,除以3余2,除以5余3, 除以7余2,求x的最小值;
     
    计算过程是:(70 * 2  + 21 *  3 + 15 * 2 ) % 105 = 23.
     
                (N1 * R1 + N2 * R2 + N3 * R3) % N   = x.
     
    其中 70(N1)是5(A2)和7(A3)的最小公倍数,对3(A1)求余为1;
         21(N2)是3(A1)和7(A3)的最小公倍数,对5(A2)求余为1;
         15(N3)是3(A1)和7(A2)的最小公倍数,对5(A3)求余为1;
         N 为3(A1),5(A2),7(A3)的最小公倍数.
     
     
    那么就可以推广到:
     
    x % A1 = R1,
    x % A2 = R2,
    x % A3 = R3,
    x % A4 = R4,
    ...... 
    x % An = Rn.
    求最小的x,其中Ai为素数;
     
    N = A1 * A2 * A3 * A4 * ... * An;
     
    所以我们要求出Ni, Ni=A1 * A2 *...* Ai-1 * Ai+1 *... * An * Ki,  根据Ni%Ai=1来确定Ki的值
     
    x = (R1*N1 + R2*N2 + R3*N3 + ... + Rn*Nn)% N ;因为要求的是:最小整数解,所以对N求余即可;
     
     
    下面关键就是求Ni,即求Ki;
    因为N是所有A的乘积,Ni为除Ai外的所有Ai的倍数,所以:
    Ni = N / Ai * K;(K为任意整数);---------式1;
    又因为Ni对Ai求余为1,所以:
    Ni = Ai * K0 + 1;(K0为任意整数);-------式2;
     
    从上面可以看出只要我们求出K或者K0就可以求出Ni了;
     
    由1,2式得N / Ai * K = Ai * K0 + 1
    化简得:(N/Ai)*K + (-Ai)K0 = 1;
    不难看出上式满足ax + by = gcd(a, b)
    由上面的分析知道N/Ai与-Ai一定互质即gcd(N/Ai, -Ai) = gcd(N/Ai, Ai) = 1;
     
    所以可以用扩展欧几里德来求解K和K0;
     
    #include<stdio.h>
    
    #define MAXN 22
    
    int n, N0;
    
    void ex_gcd(int a, int b, int &x, int &y)
    {
        if(b==0)
        {
            x = 1;
            y = 0;
            return ;
        }
        ex_gcd(b, a%b, x, y);
    
        int temp = x;
    
        x = y;
    
        y = temp - a/b * y;
    
        if(a*b<0)///如果a和b异号那么x和y取反;理由不太清楚;
        {
            x = -x;
            y = -y;
        }
    }
    
    int China(int N[], int A[], int R[])
    {
        int x = 0;
    
        for(int i=1; i<=n; i++)
        {
            int K, K0;
    
            ex_gcd(N0/A[i], -A[i], K, K0);
    
            N[i] = A[i] * K0 + 1; ///或者 N[i] = N0/A[i] * K;
    
            x = (x + N[i] * R[i] + N0) % N0;
        }
        return (x+N0)%N0;///防止出现负数;
    }
    
    int main()
    {
        int A[MAXN], R[MAXN],  N[MAXN];
    
        scanf("%d", &n);
    
        N0 = 1;
    
        for(int i=1; i<=n; i++)
        {
            scanf("%d %d", &A[i], &R[i]);
    
            N0 *= A[i];
        }
        int x = China(N, A, R);
    
        printf("%d
    ", x);
    
        return 0;
    }
    

      

  • 相关阅读:
    数据类型对照表
    MySql
    操作MongoDB
    Linux常用命令
    MongoDB性能参数
    有关Remoting的几个结论与论证
    异步获取远程文件
    Bigtable:一个分布式的结构化数据存储系统(转)
    windbg命令
    C#下几种排序算法
  • 原文地址:https://www.cnblogs.com/zhengguiping--9876/p/5319813.html
Copyright © 2011-2022 走看看