[ 模運算 ] 與 [ 模取冪運算 ]

來源:互聯網
上載者:User

很多地方用到模運算,這裡說明模運算的一些規律,並加以證明。 後續會對這些理論實際的應用加以記錄和說明。

1. 模運算是取餘運算(記做 % 或者 mod),具有周期性的特點。 m%n的意思是n除m後的餘數, 當m遞增時m%n呈現周期性特點, 並且n越大,周期越長,周期等於n。
     例如
        0 % 20 = 0,1 % 20 = 1, 2 % 20 = 2, 3 % 20 = 3, ..., 19 % 20 = 19
       20 % 20 = 0,21 % 20 = 1,22 % 20 = 2,23 % 20 = 3, ...,39 % 20 = 19
2. 如果 m % n = r,那麼可以推出如下等式
     m = k * n + r (k為大於等於0的整數, r <= m)
3. 同餘式, 表示正整數a,b對n模數,它們的餘數相同,記做 a ≡ b mod n或者a = b (mod n)。
    根據2的等式可以推出 a = kn + b 或者 a - b = kn
    證明:   ∵ a = k1 * n + r1
                    b = k2 * n + r2
               ∴ a - b = (k1 - k2) * n + (r1 - r2)
                  a = k * n + (r1 - r2) + b
              ∵ a, b對n模數同餘,r1 = r2
              ∴ a = k * n + b (k = k1 - k2)
4. 模運算規則, 模運算與基本四則運算有些相似,但是除法例外。其規則如下
    (a + b) % n = (a % n + b % n) % n            (1)
    (a - b) % n = (a % n - b % n) % n              (2)
    (a * b) % n = (a % n * b % n) % n             (3)
    ab % n = ((a % n)b) % n                             (4)

相關證明:http://hi.baidu.com/ckh%5F0330/blog/item/bb2c4d8873df60ba0e24441e.html

模取冪運算a^b mod c :

直接插入主題:

1.當a,b,c 都比較小的時候,可以使用赤裸裸的暴力
虛擬碼:
v:=1;
for i := 1 to b begin
v:=v*a;
v:=v mod c;
end

這也是我們在第一次遇到這種問題的時候首先能想到的.

2.a,b,c都比較大的時候
這裡需要考慮c的大小了,假設c*c<2^64吧(再大就只能再做特殊處理了)
b比較大的話使用1的方法顯然時間上是承受不了的,所以可以利用所謂的二分法.
b=b0+b1*2^1+b2*2^2+...+bn*2^n
顯然a^b可以變成若干項的乘積
虛擬碼:
v:=1;
while b<>0 do begin
if (b and 1= 1) do begin v:=v*a;v:=v mod c;end
a:=a*a;
a:=a mod c;
b:=b shr 1;
end
3.如果c很大,那麼需要使用到類比乘法來避免溢出,當然如果c已經大到10^100,那麼只能用高精了..這裡只能處理最多c=2^64-1的情況吧

虛擬碼:
int mul(int a,int b,int c)
{
int ret=0,tmp=a%c;
while(b)
{
   if(b&0x1)if((ret+=tmp)>=c)ret-=c;
   if((tmp<<=1)>=c)tmp-=c;
   b>>=1;
}
return ret;
}

4.如果b已經爆大,那麼使用logb的演算法顯然已經力不從心
於是可以考慮利用迴圈節的方法來求解
如果c比較小,那麼可以直接暴力得到迴圈節
對於a^b mod c

a.if gcd(a,c)==1
那麼可以知道它的迴圈節開始位置必然是1,而且迴圈節長既為它的歐拉函數的因子
因為有a^p mod c= 1
所以p可以看成是周期
b.if gcd(a,c)!=1 那麼迴圈節是否一定不從1開始呢?答案是否定的
why?
因為假設存在某個L'使
a mod c = a^(1+L') mod c= a* a^L' mod c
那麼可以解到許多滿足條件的B',使a*B' = a mod c (mod c)
解的個數就是gcd(a,c),然後如果能找到a^L' = B' (mod c)
那麼其開始位置依然可以是1
當然其他大多數情況下迴圈節開始位置都不是1

好了下面用暴力得到了迴圈節開始位置spos,和迴圈節長len

下面用到公式
就可以在比較快的時間內求解了

如果c非常大那怎麼辦?

可以利用抽屜原理+baby-step,giant-step擴充應該可以得到迴圈節的長度,接下來迴圈節的開始位置我還沒有想到比較好的演算法,暫時只能暴力了-_-,誰有思路請留言謝謝~

ps:acm競賽經常要用到模運算和模取冪運算,高優的演算法同時也要兼顧處理的範圍。

資料來自:http://hi.baidu.com/aekdycoin
               http://hi.baidu.com/ckh%5F0330

 

本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/akof1314/archive/2009/07/29/4391119.aspx

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.