• 中国剩余定理 (CRT)


    中国剩余定理,又名孙子定理

    能求解什么问题呢?

    问题:

    一堆物品

    3个3个分剩2个

    5个5个分剩3个

    7个7个分剩2个

    问这个物品有多少个

    中国剩余定理给出了以下的一元线性同余方程组:
    中国剩余定理1
     
    中国剩余定理说明:假设整数m1,m2, ... ,mn两两互质,则对任意的整数:a1,a2, ... ,an,
     方程组(S)
    有解,并且通解可以用如下方式构造得到:
     中国剩余定理2
    是整数m1,m2, ... ,mn的乘积,并设
     中国剩余定理3
    是除了mi以外的n- 1个整数的乘积。
     中国剩余定理4
    这个就是逆元了
     中国剩余定理5 
    通解形式为
     中国剩余定理6 
    在模M的意义下,方程组(S)只有一个解:
     中国剩余定理7
     
     
    注意这样求解的一定要满足: m1,m2,....,mn 两两互质
     1 LL inv(LL t,LL p){   // t 关于 p 的逆元
     2     LL x,y,d;
     3     d = ex_gcd(t,p,x,y);
     4     if (d == 1){
     5         return (x%p+p)%p;
     6     }else
     7         return -1;
     8 }
     9 
    10 
    11 // n个方程: x = a[i](mod m[i])   (0<=i<n)
    12 
    13 LL china(int n,LL *a,LL *m){
    14     LL M = 1,ret = 0;
    15     for (int i=0;i<n;i++){
    16         M *= m[i];
    17     }
    18     for (int i=0;i<n;i++){
    19         LL w = M/m[i];
    20         ret = (ret + inv(w,m[i]) * w * a[i]) % M;
    21     }
    22     return (ret + M) % M;
    23 }

    但是如果遇到不是互质的模线性方程组我们要怎么办呢?

    问题描述:给出bi,ni的值,且n1, n2, n3,…, ni两两之间不一定互质,求Res的值? 
    解:采用的是合并方程的做法。 
    这里将以合并第一第二个方程为例进行说明 
    由上图前2个方程得(设k1、k2为某一整数):
     
     
     

    例题: hdu 1573 X问题 【下面已给出代码】 
    http://acm.hdu.edu.cn/showproblem.php?pid=1573 

     1 #include <iostream>
     2 #include <algorithm>
     3 
     4 typedef long long LL;
     5 
     6 using namespace std;
     7 
     8 int N;
     9 
    10 
    11 LL ex_gcd(LL a,LL b,LL &x,LL &y){
    12     if (b == 0){
    13         x = 1;
    14         y = 0;
    15         return a;
    16     }
    17     LL gcd = ex_gcd(b,a%b,y,x);
    18     y -= (a/b)*x;
    19     return gcd;
    20 }
    21 
    22 LL inv(LL t,LL p){   // t 关于 p 的逆元
    23     LL x,y,d;
    24     d = ex_gcd(t,p,x,y);
    25     if (d == 1){
    26         return (x%p+p)%p;
    27     }else
    28         return -1;
    29 }
    30 
    31 
    32 // n个方程: x = a[i](mod m[i])   (0<=i<n)
    33 
    34 LL china(int n,LL *a,LL *m){
    35     LL M = 1,ret = 0;
    36     for (int i=0;i<n;i++){
    37         M *= m[i];
    38     }
    39     for (int i=0;i<n;i++){
    40         LL w = M/m[i];
    41         ret = (ret + inv(w,m[i]) * w * a[i]) % M;
    42     }
    43     return (ret + M) % M;
    44 }
    45 
    46 LL CRT(LL b[],LL n[],int num){
    47     bool flag = false;
    48     LL n1 = n[0],n2,b1 = b[0],b2,bb,d,t,k,x,y;
    49     for (int i=1;i<num;i++){
    50         n2 = n[i],b2 = b[i];
    51         bb = b2 - b1;
    52         d = ex_gcd(n1,n2,x,y);
    53         if (bb%d){
    54             flag = true;
    55             break;
    56         }
    57         k = bb / d * x;
    58         t = n2 / d;
    59         if (t<0)
    60             t = -t;
    61         k = (k % t + t) % t;
    62         b1 = b1 + n1 * k;
    63         n1 = n1 / d * n2;
    64     }
    65     if (flag)     //无解
    66         return 0;
    67     if (b1 == 0)   // 如果解为0,题目要求正整数解,显然不可以
    68         b1 = n1;   // n1为所以n[i] 的最小公倍数
    69     if (b1>N)
    70         return 0;
    71     return (N-b1) / n1 + 1;      //形成的解:b1, b1+n1, b1+2n1,..., b1+xni...
    72 }
    73 
    74 
    75 int main(){
    76     int t,num;
    77     LL b[10],n[10];
    78     scanf("%d",&t);
    79     while (t--){
    80         scanf("%d%d",&N,&num);
    81         for (int i=0;i<num;i++){
    82             scanf("%lld",&n[i]);
    83         }
    84         for (int i=0;i<num;i++){
    85             scanf("%lld",&b[i]);
    86         }
    87         printf("%lld
    ",CRT(b,n,num));
    88     }
    89     return 0;
    90 }


     

  • 相关阅读:
    HashMap原理
    高并发架构系列:MQ消息队列的12点核心原理总结
    大话程序员系列:一张图道尽程序员的出路
    java面试题
    SpringBoot框架的使用
    java开发定时任务执行时间
    OpenLayers 3 扩展插件收集
    Vue-cli webpack模板
    Spring的属性文件properties使用注意
    FullBg-网页图片背景自适应大小
  • 原文地址:https://www.cnblogs.com/-Ackerman/p/11352769.html
Copyright © 2020-2023  润新知