zoukankan      html  css  js  c++  java
  • 大数取余

    有一类题目会因为求出的结果太大而只要求输出对某个数m取余后的结果,而且这个m是比较小的数,比如不超过32位整数…
    而这类大数都是可以由较小的数经过某些运算得到的…
    于是我整理了一下对付几种运算的方法…包括四则运算,指数,组合数,塔函数的应对方法…

    那么就开始吧…慢慢来…
    首先是最常识的加减法:

    add_mod(a,b,m){ return ((a%m)+(b%m))%m; }

    别小看加法哦…很多用dp解的题目中靠着加法可是能达到很大的数呢…

    minus_mod(a,b,m){ return (a-b+m)%m; }

    减法…会遇到吗?

    接着是依然很简单的乘法:

    multiply_mod(a,b,m){ return ((a%m)*(b%m))%m; }

    这是当m*m不会溢出时可以用的,同时也是通常的情况…
    但是如果m*m连long long都会溢出的话…就需要把一个数一位位拆开来做了…

    multiply_mod(a,b,m){ if(b==0)return 0; return (((b&1)?a:0)+(multiply_mod(a,b>>1,m)<<1)%m)%m; }

    然后是除法,但有点限制:
    (a/b)%m
    特殊条件:m和b互质
    前提:a能被b整除
    这个有点特殊,意为虽然不知道a是多少,但是已知c,而且c=a%m,用c和b来求(a/b)%m的方法
    虽然需要m和b互质,但是不互质的话也是可以做的,因为a也一定是gcd(b,m)的倍数,具体可以看看这里

    需要用到扩展欧几里德来求…
    至于扩展欧几里德是什么…去Google一下吧…

    extend_euclid(a,b,&x0,&y0){ if(b==0){ x0=1; y0=0; return a; } r=extend_euclid(b,a%b); t=x0; x0=y0; y0=t-a/b*y0; return r; } divide_mod(a,b,m){ extend_euclid(b,m,x0,y0); return (a*(((x0%m)+m)%m))%m; }

    这个在求组合数的时候可能用到…
    不过似乎很少遇到需要用除法取余的情况呢…

    然后是更大却很简单的幂运算:
    (a^b)%m
    这是初学递归或者二分时就会遇上的一个很简单的方法,和之前的乘法差不多

    power_mod(a,b,m){ if(b==0)return 1; if(b&1)return (a*power_mod((a*a)%m,b>>1,m))%m; else return power_mod((a*a)%m,b>>1); }

    其中乘法取余会运算中溢出的话可以改成之前那个multiply_mod()

    恩…开始有趣了…下面是组合数:
    C(a,b)%m
    特殊条件:m是质数
    如果b或者a-b比较小的话,可以用之前计算(a/b)%m的方式来把组合数公式展开来计算
    不过当b和a-b与m相比很大时,有更好的方法:
    a,b在m进制下表示为 a=(ak,…,a0),b=(bk,…,b0) 0=<ai,bi<m
    于是会有这样的性质:

    C(a,b)=C(ak,bk)*...*C(a0,b0) (mod m)

    最后是难以想象的大的数…塔函数:
    (a↑↑b)%m
    这里可以看到其一些性质
    比如Project Euler 282
    Ackermann 函数就是非常恶心的大数
    第一层是很小的常数,第二层是n个a相加,也就是乘法,第三层是n个a相乘,也就是幂,第四层是n个a叠着做幂即塔函数,第k+1层是n个a做第k层运算…
    用小数字居然也能表示出如此之大的数…佩服啊…
    上一篇中也有提到:

    n>=phi(m)时,a^n=a^(n%phi(m)+phi(m)) (mod m)

    其中phi()是欧拉函数
    由于phi(x)<x,所以就算是对a↑↑b这样大的数也总会在足够短的时间内收敛,然后计算出(mod m)的值
    这个不止在塔函数中,也可以用在各种指数异常大的情况下
    特别的,在b>m的情况下,(a↑↑b)%m的值将是定值

    恩…就到这里了…

  • 相关阅读:
    LeetCode Count of Range Sum
    LeetCode 158. Read N Characters Given Read4 II
    LeetCode 157. Read N Characters Given Read4
    LeetCode 317. Shortest Distance from All Buildings
    LeetCode Smallest Rectangle Enclosing Black Pixels
    LeetCode 315. Count of Smaller Numbers After Self
    LeetCode 332. Reconstruct Itinerary
    LeetCode 310. Minimum Height Trees
    LeetCode 163. Missing Ranges
    LeetCode Verify Preorder Serialization of a Binary Tree
  • 原文地址:https://www.cnblogs.com/Wu-Shi/p/5410059.html
Copyright © 2011-2022 走看看