zoukankan      html  css  js  c++  java
  • 数论--中国剩余定理

    中国剩余定理:

    国务院:中国油气人均剩余可采存储量仅为世界平均的6%...

    咳咳,不对,不是这个

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

    听说过韩信点兵吗?

    韩信带1500名兵士打仗,战死四五百人,站3人一排,多出2人;站5人一排,多出4人;站7人一排,多出6人。韩信很快说出人数:1049。

    韩信一定是读过《孙子算经》的,

    书里面有这样一道算术题:“今有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二,问物几何?”

    也就是:

    一堆物品,

    3个3个分剩2个,

    5个5个分剩3个,

    7个7个分剩2个,

    问这个物品有多少个?

    解这题,我们需要构造一个答案

    我们需要构造这个答案

    5*7*inv(5*7,  3) % 3  =  1

    3*7*inv(3*7,  5) % 5  =  1

    3*5*inv(3*5,  7) % 7  =  1

    这3个式子对不对,别告诉我逆元你忘了(*´∇`*),忘了的人请翻阅前几章复习

    然后两边同乘你需要的数

    2 * 5*7*inv(5*7,  3) % 3  =  2

    3 * 3*7*inv(3*7,  5) % 5  =  3

    2 * 3*5*inv(3*5,  7) % 7  =  2

    令 

    a = 2 * 5*7*inv(5*7,  3) 

    b = 3 * 3*7*inv(3*7,  5) 

    c = 2 * 3*5*inv(3*5,  7) 

    那么

    a % 3 = 2

    b % 5 = 3

    c % 7 = 2

    其实答案就是a+b+c

    因为

    a%5 = a%7 = 0 因为a是5的倍数,也是7的倍数

    b%3 = b%7 = 0 因为b是3的倍数,也是7的倍数

    c%3 = c%5 = 0 因为c是3的倍数,也是5的倍数

    所以

    (a + b + c) % 3 = (a % 3) + (b % 3) + (c % 3) = 2 + 0 + 0 = 2

    (a + b + c) % 5 = (a % 5) + (b % 5) + (c % 5) = 0 + 3 + 0 = 3

    (a + b + c) % 7 = (a % 7) + (b % 7) + (c % 7) = 0 + 0 + 2 = 2

    你看你看,答案是不是a+b+c(。・ω・)ノ゙,完全满足题意

    但是答案,不只一个,有无穷个,每相隔105就是一个答案(105 = 3 * 5 * 7)

    根据计算,答案等于233,233%105 = 23

    如果题目问你最小的那个答案,那就是23了

    (233怎么算的呢?

        a=2*5*7*2=140;

        b=3*3*7*1=63;

        c=2*3*5*1=30;

     140+63+30=233;

       hhh2333333333333333,答案233出来了吧,hhh,不会算逆元的小伙伴该回去复习逆元了!)

    以下抄自百度百科

    中国剩余定理给出了以下的一元线性同余方程组:
    中国剩余定理1
     
    中国剩余定理说明:假设整数m1,m2, ... ,mn两两互质,则对任意的整数:a1,a2, ... ,an,
     方程组(S)
    有解,并且通解可以用如下方式构造得到:
     中国剩余定理2
    是整数m1,m2, ... ,mn的乘积,并设
     中国剩余定理3
    是除了mi以外的n- 1个整数的乘积。
     中国剩余定理4
    这个就是逆元了
     中国剩余定理5 
    通解形式为
     中国剩余定理6 
    在模M的意义下,方程组(S)只有一个解:
     中国剩余定理7
     
    那么代码来了:
     1 #include<cstdio>
     2 
     3 typedef long long LL;
     4 
     5 LL inv(LL t, LL p) {//求t关于p的逆元 
     6     if(t>=p)
     7     t=t%p;
     8     return t == 1 ? 1 : (p - p / t) * inv(p % t, p) % p;
     9 }
    10 
    11 //n个方程:x=a[i](mod m[i]) (0<=i<n)
    12 LL china(int n, LL m[], LL a[]){
    13     LL M = 1, ret = 0;
    14     for(int i = 0; i < n; i ++) M *= m[i];
    15     for(int i = 0; i < n; i ++){
    16         LL w = M / m[i]; 
    17         ret = (ret + w * inv(w, m[i]) * a[i]) % M;
    18     }
    19     return (ret + M) % M;
    20 }
    21 int main(){
    22     int n;
    23     LL m[2000],a[2000];
    24     scanf("%d",&n);
    25     for(int i=0;i<n;i++)
    26     {
    27         scanf("%d%d",&m[i],&a[i]);
    28      } 
    29      printf("%lld
    ",china(n,m,a));
    30 }

    3个式子:

    x%3=2

    x%5=3

    x%7=2

    求x;

    运行程序,输入

    3

    3 2

    5 3

    7 2

    试试看答案是不是23

    告诉你一个好消息,上面这个中国剩余定理只是基础,2333333333,是要求m数组里面的元素两两互质的!

    那如果不一定是呢?怎么办?

    上模板吧:

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 typedef long long LL;
     5 typedef pair<LL, LL> PLL;
     6 
     7 LL inv(LL t, LL p) {//求t关于p的逆元 
     8     if(t>=p)
     9     t=t%p;
    10     return t == 1 ? 1 : (p - p / t) * inv(p % t, p) % p;
    11 }
    12 
    13 PLL linear(LL A[], LL B[], LL M[], int n) {//求解A[i]x = B[i] (mod M[i]),总共n个线性方程组 
    14     LL x = 0, m = 1;
    15     for(int i = 0; i < n; i ++) {
    16         LL a = A[i] * m, b = B[i] - A[i]*x, d = __gcd(M[i], a);
    17         if(b % d != 0)  return PLL(0, -1);//答案不存在,返回-1 
    18         LL t = b/d * inv(a/d, M[i]/d)%(M[i]/d);
    19         x = x + m*t;
    20         m *= M[i]/d;
    21     }
    22     x = (x % m + m ) % m;
    23     return PLL(x, m);//返回的x就是答案,m是最后的lcm值 
    24 }
    25 
    26 int main()
    27 {
    28     int n;
    29     scanf("%d",&n);
    30     LL a[2017],b[2017],m[2017];
    31     for(int i=0;i<n;i++)
    32     {
    33         scanf("%d%d%d",&a[i],&b[i],&m[i]);
    34     }
    35     PLL pa=linear(a,b,m,n);
    36     printf("%lld
    ",pa.first);
    37 }

    1*x=2(%3)

    1*x=3(%5)

    1*x=2(%7)

    输入:

    3

    1 2 3

    1 3 5

    1 2 7

    输出:

    23

    有兴趣的可以去试试这道题

    poj 2891

    http://poj.org/problem?id=2891

  • 相关阅读:
    freemarker模板引擎 常用标签
    SSH面试题
    JAVA 2013面试题-下
    JAVA 2013面试题-上
    String和StringBuffer
    http请求和http响应详细解析
    一种将汉字转换为拼音的更简单的方法
    中文字符串排序
    UIControl类控件统一管理
    日期转换
  • 原文地址:https://www.cnblogs.com/eastblue/p/7635006.html
Copyright © 2011-2022 走看看