欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

組合數(shù)取模Lucas定理及快速冪取模

系統(tǒng) 2086 0

  組合數(shù) 取模就是求 的值,根據(jù) 的取值范圍不同,采取的方法也不一樣。

下面,我們來(lái)看常見的兩種取值情況(m、n在64位整數(shù)型范圍內(nèi))

(1) ? ,

???? 此時(shí)較簡(jiǎn)單,在O(n 2 )可承受的情況下組合數(shù)的計(jì)算可以直接用楊輝三角遞推,邊做加法邊取模。

(2) , ? ,并且 是素?cái)?shù)

?  本文針對(duì)該取值范圍較大又不太大的情況(2)進(jìn)行討論。

???? 這個(gè)問題可以使用 Lucas 定理,定理描述:

 其中

????

???? 這樣將組合數(shù)的求解分解為小問題的乘積,下面考慮計(jì)算 C(ni, mi) %p .

 已知C(n, m) mod p = n!/(m!(n - m)!) mod p。當(dāng)我們要求(a/b)mod p的值,且a很大,無(wú)法直接求得a/b的值時(shí),我們可以轉(zhuǎn)而使用乘法逆元k,將a乘上k再模p,即(a*k) mod p。 其結(jié)果與(a/b) mod p等價(jià)。

那么逆元是什么?

    
      定義:滿足a*k≡1 (mod p)的k值就是a關(guān)于p的乘法
      
        逆元
      
      (當(dāng)p是1時(shí),對(duì)于任意a,k都為1)
    
  

除法取模,這里要用到m!(n-m)!的逆元。

根據(jù) 費(fèi)馬小定理

已知gcd(a, p) = 1,則 a p-1 ?≡ 1 (mod p), ?所以 a*a p-2 ?≡ 1 (mod p)。

也就是 (m!(n-m)!)的逆元為 (m!(n-m)!) p-2 ;

下面附上Lucas定理的一種證明,見下圖,參考馮志剛《 初等數(shù)論 》第37頁(yè)。

組合數(shù)取模Lucas定理及快速冪取模

題意: ,其中 ,并且 是素?cái)?shù)。

代碼:

        
          #include<iostream>


          
            //
          
          
            #include<algorithm>
          
          
            using
          
          
            namespace
          
          
             std; typedef 
          
          
            long
          
          
            long
          
          
             ll; 
          
          
            int
          
           quick_power_mod(
          
            int
          
           a,
          
            int
          
           b,
          
            int
          
           m){
          
            //
          
          
            pow(a,b)%m
          
          
            int
          
           result = 
          
            1
          
          
            ; 
          
          
            int
          
          
            base
          
           =
          
             a; 
          
          
            while
          
          (b>
          
            0
          
          
            ){ 
          
          
            if
          
          (b & 
          
            1
          
          ==
          
            1
          
          
            ){ result 
          
          = (result*
          
            base
          
          ) %
          
             m; } 
          
          
            base
          
           = (
          
            base
          
          *
          
            base
          
          ) %
          
            m; b
          
          >>=
          
            1
          
          
            ; } 
          
          
            return
          
          
             result; } 
          
          
            //
          
          
            計(jì)算組合數(shù)取模
          
          

ll comp(ll a, ll b, 
          
            int
          
           p) {
          
            //
          
          
            composite num C(a,b)%p
          
          
            if
          
          (a < b)   
          
            return
          
          
            0
          
          
            ; 
          
          
            if
          
          (a == b)  
          
            return
          
          
            1
          
          
            ; 
          
          
            if
          
          (b > a - b)   b = a -
          
             b; 
          
          
            int
          
           ans = 
          
            1
          
          , ca = 
          
            1
          
          , cb = 
          
            1
          
          
            ; 
          
          
            for
          
          (ll i = 
          
            0
          
          ; i < b; ++
          
            i) { ca 
          
          = (ca * (a - i))%
          
            p; cb 
          
          = (cb * (b - i))%
          
            p; } ans 
          
          = (ca*quick_power_mod(cb, p - 
          
            2
          
          , p)) %
          
             p; 
          
          
            return
          
          
             ans; } ll lucas(ll n, ll m, ll p) { ll ans 
          
          = 
          
            1
          
          
            ; 
          
          
            while
          
          (n&&m&&
          
            ans) { ans 
          
          = (ans*comp(n%p, m%p, p)) % p;
          
            //
          
          
            also can be recusive
          
          

        n /=
          
             p; m 
          
          /=
          
             p; } 
          
          
            return
          
          
             ans; } 
          
          
            int
          
          
             main(){ ll m,n; 
          
          
            while
          
          (cin>>n>>
          
            m){ cout
          
          <<lucas(n,m,
          
            10007
          
          )<<
          
            endl; } 
          
          
            return
          
          
            0
          
          
            ; }
          
        
      
View Code

? 上面的代碼中用到了求冪取模操作來(lái)計(jì)算(m!(n-m)!) p-2 % p.下面解釋冪取模算法:

反復(fù)平方法 求a b %m

通過研究指數(shù)b的二進(jìn)制表示發(fā)現(xiàn),對(duì)任意的整數(shù)b都可表示為:


  • n表示b的實(shí)際二進(jìn)制位數(shù)
  • b i 表示該位是0或1

因此,a b 可表示為:

即用b的每一位表示a的每一項(xiàng),而對(duì)任意相鄰的兩項(xiàng)存在平方關(guān)系,即:

因此我們構(gòu)造下面的算法:

    • 把b轉(zhuǎn)換為二進(jìn)制表示,并從右至左掃描其每一位(從低到高)
    • 當(dāng)掃描到第i位時(shí),根據(jù)同余性質(zhì)(2)計(jì)算a的第i項(xiàng)的模:

      base變量表示第i-1位時(shí)計(jì)算出的模,通過遞歸能很容易地確定所有位的模。
    • 如果第i位為1,即b i =1,則表示該位需要參與模運(yùn)算,計(jì)算結(jié)果 result = (result*base) mod m;其中result為前i-1次的計(jì)算結(jié)果;若b i =0,則表示a的第i項(xiàng)為1,不必參與模運(yùn)算
    
      int quick_power_mod(int a,int b,int m){

    int result = 1;

    int base = a;

    while(b>0){

         if(b & 1==1){

            result = (result*base) % m;

         }

         base = (base*base) %m;

         b >>=1;

    }

    return result;

}
    
  

其中運(yùn)用了兩個(gè)同余性質(zhì):

同余性質(zhì)1:ab≡bc (mod m)

同余性質(zhì)2: ? a≡c (mod m) => a 2 ≡c 2 (mod m)

理解要點(diǎn):

  • base記錄了a的每項(xiàng)的模,無(wú)論b在該位是0還是1,該結(jié)果都記錄,目的是給后續(xù)位為1的項(xiàng)使用,計(jì)算方式是前一結(jié)果的平方取模,這也是反復(fù)平方法的由來(lái)
  • result只記錄了位為1的項(xiàng)的模結(jié)果,該計(jì)算方式使用了同余性質(zhì)1
  • 通過地把a(bǔ)使用二進(jìn)制表示,并結(jié)合同余性質(zhì)1,2,巧妙地化解了大數(shù)取模的運(yùn)算。對(duì)1024位這樣的大數(shù),也最多進(jìn)行1024次循環(huán)便可計(jì)算模值,性能非常快。

該方法是許多西方數(shù)學(xué)家努力的結(jié)果,通常也稱為Montgomery算法。

(以上部分內(nèi)容由網(wǎng)絡(luò)搜集整理而來(lái),不當(dāng)之處,煩請(qǐng)不吝賜教)

?

組合數(shù)取模Lucas定理及快速冪取模


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 天天操狠狠操夜夜操 | 日本高清www午色夜黄 | 一区二区三区亚洲 | 欧美成人手机在线视频 | 手机看片日韩国产 | 免费在线公开视频 | 色噜噜狠狠色综合欧洲selulu | 欧洲成人一区 | 精品在线视频播放 | 国产亚洲精品久久精品录音 | 日韩18在线观看地址 | 免费成人在线网站 | 香蕉福利久久福利久久香蕉 | 日韩欧美一区二区在线观看 | 草逼com | 亚洲视频1 | 69久久 | 欧美一区二区三区免费不卡 | a级在线观看 | 国产成人精品免费久久久久 | 日本a毛片| 亚洲高清视频一区二区 | 在线国产视频 | 小明永久免费 | 国产欧美日韩一区 | 91精品国产综合久久久久久 | 91短视频在线高清hd | 国产亚洲精品久久久久久久久动漫 | 精品视频一区二区 | 香蕉国产人午夜视频在线观看 | 日韩www| 国产高清美女一级毛片 | 久久一日本道色综合久久 | 婷婷久月| 高清一区二区亚洲欧美日韩 | 一级毛片 在线播放 | 婷婷色国产偷v国产偷v小说 | 国产欧美日韩在线观看 | 欧美精品一二三区 | 无限资源动漫精彩日本 | caoliushequ2017|