• 对于中国剩余定理(CRT)的初步理解


    以前觉得用中国剩余定理来求同余方程组很鸡肋,因为可以用拓展欧几里得算法来构造出一种更加强大(可以处理取模的数(默认为mi)不互质的情况)的算法。

    今天查了点资料,发现我太天真了。

    首先讲讲中国剩余定理:

    即 : x ≡ a[i] (mod m[i]) 1<= i <= r (m[i] 两两互质)

    求这个同余方程组可以快速算:

    x = ∑M/m[i] * Inv(M/m[i], m[i]) * a[i] (mod M) 其中M = m[1]*m[2]*m[3]...m[r]  , Inv(x, y) 表示x在模y下的逆元

    讲讲我对这个方程的理解:

    1) 因为m[i]是两两互质的,所以gcd(M/m[i], m[i]) == 1,也就是说逆元一定存在,所以这个方程一定有解(对m[i]两两不一定互质的情况要小心解不存在的情况,即逆元不存在)。

    2) 然后,为什么这个解就一定是这个同余方程组的解呢?是这样的,首先M/m[i] 对于除了m[i]外其他的m[k]的话都是能够被整除的,而M/m[i] * Inv(M/m[i], m[i])*a[i]这一部分对m[i]取模肯定是a[i],因为M/m[i] * Inv(M/m[i], m[i]) ≡ 1(mod m[i]),所以∑M/m[i] * Inv(M/m[i], m[i]) * a[i]肯定是满足要求的一个解。

    3) 代码实现

     1 typedef long long lld;
     2 lld exgcd(lld a, lld b, lld &x, lld &y) {
     3     if (!b) {
     4         x = 1; y = 0;
     5         return a;
     6     }
     7     lld ret = exgcd(b, a % b, y, x);
     8     y -= (a/b) * x;
     9     return ret;
    10 }
    11 lld Inv(lld a, lld MOD) {
    12     lld x, y;
    13     lld d = exgcd(a, MOD, x, y);
    14     return d == 1 ? (x%MOD+MOD)%MOD : printf("no~\n");
    15 }
    16 lld China(int a[], int n, int m[]) {
    17     lld M = 1, ret = 0;
    18     for (int i = 1; i <= n; i++) M *= m[i];
    19     for (int i = 1; i <= n; i++) {
    20         lld w = M/m[i];
    21         ret = (ret + w * Inv(w, m[i])% M * a[i] % M) % M;
    22     }
    23     return ret;
    24 }
    View Code

    独立剩余:

    其实上面的内容就是我觉得“鸡肋”的地方,恩,有关独立剩余才是真正的体现CRT用处的地方,由于我自己现在还只是初步的了解,所以有可能出错,敬请原谅。

    同余式: Res(x) = (x mod m[1], ..., x mod m[r]), 且m[i]两两互质 对于一个大于1的数x,我们都可以表示 x = ∏p[i] ^ {k[i]} k[i] >= 1,所以很多地方一个数你可以拆成多个不同的素数的积,这样两两互质这一条件一定成立。

    然后同余式有个规则(?)就是我们可以在每一个分量上进行独立的执行加法,减法和乘法。 这是一个很赞的地方,比如对于一个M = 30 , 我们可以对于2、3、5分别进行模运算,最通过"某种方法“还原成对于30的模运算结果,这往往可以获得意想不到的效果(虽然我还没做过类似的题目= =)

    哦,所谓的”某种方法“就是中国剩余定理,我们可以类似的向量般的处理(1, 0, 0) = a, (0, 1, 0) = b, (0, 0, 1) = c对于M = 30我们可以把它看做一个三维向量,那么(x, y, z) = (a*x+b*y+c*z) mod 30

    现在我们需要的是计算出a、b、c的值,当然如果M比较小的话,你可以暴力去找,复杂度O(M),M较大的时候就可以套中国剩余定理了,不过不用∑,也就是M/m[i] * Inv(M/m[i], m[i]) * a[i], 这么一项就行了,(其实只要算一个拓展欧几里得的就行了,只是样子有点象CRT而已 = =) 

    好吧,暂时理解就到这了(写这个主要还是加深印象)= =,继续看书... 未完待续....勿喷....

  • 相关阅读:
    java之集合Collection 3个例子
    利用 ssh 的用户配置文件 config 管理 ssh 会话
    angularJS--apply() 、digest()和watch()方法
    37.创业团队不是天堂
    Android DiskLruCache 源码解析 硬盘缓存的绝佳方案
    sublime安装AngularJS插件
    angularJS 服务--$provide里factory、service方法
    angularJS--多个控制器之间的数据共享
    angularJS---自定义过滤器
    依赖反转
  • 原文地址:https://www.cnblogs.com/danceonly/p/3901595.html
Copyright © 2020-2023  润新知