** 1.快速冪的演算法**
(1)當我們求乙個數的n次方的的結果時,若直接選擇for迴圈,來累乘的話,效率很低,時間複雜度位o(n),而當我們選擇快速冪來計 算時,時間複雜度能達到o(logn),快了很多。快速冪的基本方法基於二進位制,將n次方分解,每次計算平方。如下:
假設我們要求5^23(5的23次方),因為23換為二進位制為:10111。即2^4*1+2^3*0+2^2*1+2^1*1+2^0*1,那麼5^23次方就可以轉換,為:5^(2^4*1)*5^(2^3*0)*5^(2^2*1)*5^(2^1*1)*5^(2^0*1)。基於這個公式,我們計算5^23次方就只需要5步就算出來了,原來則需要計算23次。效率提高不少,特別是當n為很大的時候,效率更高。那麼,現在有個問題,怎麼算這五步呢?思路如下:
1.觀察這五個等式,從高到低依次為5^16,5^8(雖然沒有,但規律是這樣),5^4,5^2,5^1[前一項是後一項的平方]
2.我們可以通過&1來得到乙個數的最後一位,可以通過》符號將二進位制往右邊移一位。
有了上面兩點,我們來實現快速冪的演算法:
long quick(long a,long n)
base*=base;//迴圈一次就平方一次,因為存在前乙個是後乙個數的平方
n>>=1; //n的二進位制往右移動一位
}return res;
}
結論:演算法不複雜,主要是&和》符號的應用,然後就是每次移動一位,就應該平方一次,因為前面的數是後面的數的平方,即使二進位制最後一位為0,也應平方一次,因為它前乙個的前面乙個是它的平方的平方,也就是4次方。
**2.大整數的大整數冪對乙個大整數求冪的結果**
1.這個問題也是基於上面的部分演算法,不過要複雜一點。首先我們需要知道的是對乙個數求模有以下的公式:
(a + b) % p = (a % p + b % p) % p (1)
(a - b) % p = (a % p - b % p) % p (2)
(a * b) % p = (a % p * b % p) % p (3)
(a ^ b) % p = ((a % p)^b) % p (4)
上面的公式就是說,乙個數求模,可以分別對構成這個數的各個數求模,然後將模進行相應的加減乘除來計算結果。
例如:(5^131287)%4,我們不可能把5^131287次方算出來,就算用計算機,這個數也是超越了計算範圍了,特別大。根據以上公式,我們知道5%4=1,(1^131287)%4=1。所以結果為1。
再比如:(16^23234)%7,因為16%7=2,所以可以轉換為求(2^23234)%7,然後我們知道(2^3)%7=1,而23234=3*7744+2。所以(2^23234)%7=( (2^3)^7744 * (2^2) )%7=1*4=4。所以結果為4
有了以上的基礎,我們可以得到以下的演算法:
public
class main
long mod(long n,long k,long m)else
if(n==m)
while(k!=0)else
if(mod>m)
base=base%m; //base求餘,根據餘數來算模,以免超出long的範圍
} base*=base; //將餘數進行平方來算模,能減小數的大小
base=base%m;
k>>=1; //將k的二進位制往右移動一位
}
return mod;}}
546471837123713的6464713次方對764求模的結果:
結論:感覺這個可能理解有點困難,不過有數論基礎的話理解應該不難的。沒接觸過數論的話,要好好理解下
快速冪和快速冪求模演算法
求 x 的 n 次方 當然,這道題你也可以採用 n 次迴圈讓 n 個 x 相乘,不過,這樣的做法毫無意義,因為估計小學生也會做。不過這道題如果知道了思路,還是挺簡單,我舉個例子吧,例如我們要求 2 8。1 首先,我們可以通過 2 2 4 得到 2 2 2 接著,我們利用剛才的結果,讓 4 4 16 ...
快速冪求模
所謂的快速冪,實際上是快速冪取模的縮寫,簡單的說,就是快速的求乙個冪式的模 餘 在程式設計過程中,經常要去求一些大數對於某個數的餘數,為了得到更快 計算範圍更大的演算法,產生了快速冪取模演算法。一.先從簡單的例子入手 先求值,在取模。演算法1.首先直接地來設計這個演算法 int ans 1 for ...
快速冪求模
演算法1.首先直接地來設計這個演算法 很容易因為數字過大而溢位。int ans 1 for int i 1 i b i ans ans a ans ans c 演算法2.根據公式a b mod c a mod c b mod c 改進為 int ans 1 a a c for int i 1 i b...