zoukankan      html  css  js  c++  java
  • 中国剩余定理(CRT) and 扩展中国剩余定理(EXCRT)

    今有物不知其数,三三数之余二;五五数之余三;七七数之余二。问物几何?

    语文水平不高,大概翻译一下:

    今天Rothen钓了几个妹子,3个3个的数会余下2个,5个5个的数会余下3个,七个七个的数会剩下2个

    好吧,这样好像更难理解了,懒得翻译了,反正大家都看得懂,大佬们就先做会吧,反正对于您这种神犇那肯定是秒切啊!。

    中国剩余定理???好高级的东西啊,吓得我赶紧来个BFS( Baidu First Search)

    发现中国剩余定理又叫孙子定理,原因是孙子发明的(这名字绝了)

    然后对于上面的题目的解法为:

    (注意,中国剩余定理的解法只能用于几个模数两两互质的情况)

    1.首先找出5和7的 mod 3等于1的公倍数(70),然后找出3和7的mod 5 等于1的公倍数(21),还有就是3 和 5的mod 7等于1的公倍数(15)

    2.答案就是上面求出来的三个数的乘积分别乘以"对应的余数" mod 所有模数的乘积 例如 (70*2+21*3+15*2)mod (7*3*5)得到23

    纳尼!这么神奇的吗?

    真的就是这么神奇哦~

    本蒟蒻查阅对于这个定理的证明为:

    把上面的问题转化为多个个子问题:

    假设存在一个数x1 % 3 =2("%"就是取余数),那么x1就能表示为3k+2的形式(k >= 0)

    假设存在一个数x2 % 5 =3("%"就是取余数),那么x1就能表示为5k+3的形式(k >= 0)

    假设存在一个数x3 % 7 =2("%"就是取余数),那么x1就能表示为7k+2的形式(k >= 0)

    那么考虑如果存在一个

    x1 + x2 + x3使得它们满足上面的所有条件呢?

    首先有个特别基础的公式:A % B = C, 那么(A + B*K) % B =C

    这个应该很好理解,你可以这么想:跟上面的类似,A可以表示为 若干倍的B加上C,

    而A+B*k就可以表示为:若干倍的B + C +K倍的B ,自然的对于(A+B*k)%B也是等于C了啊!

    回到刚才的问题,怎么样才能使得x1+x2+x3满足条件呢?

    若要使得(x1+x2+x3)%3仍然余下2,那么x2,x3就一定要是三的倍数

    若要使得(x1+x2+x3)%5仍然余下3,那么x1,x3就一定要是五的倍数

    若要使得(x1+x2+x3)%7仍然余下2,那么x1,x2就一定要是七的倍数

     所以问题就转化为了求出x1,x2,x3

    哦吼,从上面我们看出了x1,x2,x3的几个性质:

    1.x1是5和7的公倍数,而且x1 % 3  = 2

    2.x2是3和7的公倍数,而且x2 % 5 =  3

    3.x3是3和5的公倍数,而且x3 % 7 =  2

    同时又引入一个数学公式:

    如果a%b=c,那么(a*k)%b=(a%b+a%b+a%b+...+a%b(k个a%b)   ) mod   b=c×k mod b

    然后问题就可以用开篇的方法解决了呀!而且找出来的是最小满足条件的数。

    妙啊!

    例题:

    P1495 【模板】中国剩余定理(CRT)/曹冲养猪

    板子,不多赘述。

    放上我这丑的一批的代码:

    #include <bits/stdc++.h>
    #define int long long
    using namespace std;
    int n,a[15],b[15],c[15],q=1,sum=0;
    signed main(){
        cin>>n;
        for (int i = 1 ; i <= n ; i ++)
        cin>>a[i]>>b[i],q*=a[i];
        for (int i = 1 ; i <= n ; i ++){
            if(a[i] == 1)continue;
            q/=a[i];
            int j=1;
            while(q*j % a[i] != 1)j++;//找其他几个数的公倍数%a[i]等于一的数
            c[i]=q*j;
            q*=a[i];
        }
        for (int i = 1 ; i <= n ; i ++)
            sum+=c[i]*b[i],sum%=q;
        cout<<sum%q;
        return 0;
    }

    注意:中国剩余定理只能用于每一个a[i]都两两互质的情况,但是如果它们不是两两互质的,我们就要用   “扩展中国剩余定理

    扩展中国剩余定理是中国剩余定理的"进阶版"

    那么扩展中国剩余定理的使用情况是怎么样的呢?

    因为上面也提到了:“注意,中国剩余定理的只能用于几个模数两两互质的情况”,所以扩展中国剩余定理就是可以适用于模数不两两互质的情况。

    那这怎么搞啊?

    聪明的数学家们又找到了一种办法:

    将原来的余数方程列出来

    假设现在我们已经求出来了前k-1个方程的解是x,现在加入了第k个方程

    设前k-1个方程的模数的乘积是M,我们现在就是要求一个数字P使得

    (x + P*M) % 第k个模数  = 第k个余数

    这个P是可以通过扩展欧几里得算法算出来的,所以就可以很快求出P来。

    这个问题又解决了,妙啊!

  • 相关阅读:
    String,StringBuffer与StringBuilder的区别??
    Android之NDK开发的简单实例
    Eclipse在线安装插件奇慢的解决办法
    Android之Windows下生成动态库so并打包到APK中
    Android打包之Ant多渠道打包的实现
    Android打包之Ant打入第三方jar包及zipalign对齐优化
    Android打包之将bat脚本转换成ant脚本
    Android打包之bat脚本打包
    利用ant和dedex解析classes.dex
    Ant详解(用Ant实现Java项目的自动构建和部署)
  • 原文地址:https://www.cnblogs.com/MYCui/p/13550519.html
Copyright © 2011-2022 走看看