前幾天,在做「有道難題」的第一次練習賽中的第二題時,最終寫了個自認為正確且速度超快的演算法,但是我不敢肯定其正確性,也無法進行有效的驗證,故現發帖廣徵大家的意見,並幫我驗證或修改此演算法,若已有類似的演算法也望大家能貼出來以共勉。
此題大概要求如下:
1、a、
b為正整數,其中,
a > 0,b < 2^31
2、求a^b mod 9907
此例可用下面2
種演算法進行求解:
1、a^b = 9907*n+m
,其中,
n >= 0
,0 <= m < 9907,m
,n均為自然數,
m即為所求餘數。
2.、此處涉及兩個公式:
1)a^b = (9907+m)^n
,其中,m,
n為自然數,
a >= 9907
,m^n mode 9907
即為所求餘數。
2)mn mode 9907 = [(m mod 9907)(n mod 9907)]mod 9907
,其中,m,
n為正整數。
用第一種原理求解,運算時間很長,而且當b
很大時,
a^b是難以直接求解的。故本演算法採用演算法2。
演算法2似乎存在侷限性,因為僅討論了
a >= 9907
的情況,若
a < 9907
該怎麼辦?是的,
a < 9907
時用演算法
2不行,但是我可以將已知條件處理一下,取一正整數x,使
a^x >= 9907
,然後,將
b賦值為b與
x的商,最後得到等式
a^b = ((a^x)^(b/x))*(a^(b%x))
(b/x,b%x為c
語言中的求商和求餘)。這樣
(a^x)^(b/x)
不就可以用演算法
2中的公式
1求解了嗎?最後再用公式
2就可以求解
a^b mod 9907了。
當b很大時,就需要用公式
1不斷降階直到階小於
x時演算法終止。用此演算法可以實現快速降階,因為每次
x都不一樣,而每次
b = b/x
,從而使
b越來越小,最後使
b < x
,假設b = 2^30=1024*1024*1024
,而a=2
,則首次降階
x=14
,b = (2^30)/14 < 1024*1024*74
,a =(2^14)%9907 = 6477
,看不出來有什麼變化嗎?那算一下
1024*1024*1024 - 1024*1024*74
等於多少吧。這可直接減掉了大約
1024*1024*950
的「贅肉」呀!接下來就只用求
6477^(1024*1024*74) mod 9907
了,如法炮製便可很快實現降階。
所以,最後的演算法概貌如下:
下面是我用c
語言寫的具體實現:
恩,就是這些了。請大家幫我檢查一下,該演算法是否有問題,或是提供一些驗證例項或方法。當然,若有更好的演算法,也希望您能與大家分享,謝謝!
求乙個矩陣的逆矩陣 用伴隨矩陣求
題目 noyj774 用代數余子式求逆矩陣方法 若現有矩陣a,要求其逆矩陣 若 a 0,則其不存在逆矩陣 若 a 0,其逆矩陣a 1 a a 其中 a為其伴隨矩陣 伴隨矩陣的求法 a j i m i j 其中m i j 為a i j 的代數余子式 即 a1 i j m i j 再將 a1轉置得到 a...
受到啟發,寫了乙個驗證輸入的簡易框架
剛才看了 種玉堂 的幾篇部落格 很受啟發,用了2個多小時寫了乙個驗證輸入的框架。基於.net 2.0的 呼叫方法如下 class class1 就是驗證123.11是否大於124,是否小於123,如果驗證不通過,就會顯示錯誤的資訊。當然,如果是.net3.5以上,會有什麼l 表示式之類的,就不需要我...
求乙個思路和乙個定義的方法
程式 百錢買百雞.prg screen.visible f.formheight 280 formwidth 375 objform createobject fm1 objform.show read events define class fm1 as form windowtype 1 sho...