快速冪與快速乘
阿新 • • 發佈:2021-01-01
a^b
題目描述
求 a 的 b 次方對 p 取模的值,其中 0≤a,b≤10^9 , 0<p≤10^9
輸入
三個用空格隔開的整數a,b和p。
輸出
一個整數,表示a^b mod p的值。
樣例輸入
2 3 9
樣例輸出
8
思路
普通求冪時間複雜度為O(b),會TLE
設b的二進位制表示有k位,ci為0或1,則
而
\[a^{2^i} = a^{2^{i-1}}*a^{2^{i-1}} \]所以計算k-1次就可以求出答案,時間複雜度優化到O(logb)
還可以用遞迴的思想
\[a^b = \left\{ \begin{aligned} & a^{\frac b2}*a^{\frac b2} &(b為偶數) \\ & a^{\frac {b-1}2}*a^{\frac {b-1}2}*a& (b為奇數)\\ \end{aligned} \right. \]程式碼
非遞迴寫法
#include<bits/stdc++.h> using namespace std; typedef long long ll; ll quick_power(ll a, ll b, ll p){ // 快速冪 ll ans = 1 % p; while(b){ if(b & 1) ans = a*ans % p; a = a*a % p; b >>= 1; } return ans; } int main(){ ll a,b,p; cin>>a>>b>>p; ll ans = quick_power(a,b,p); cout<<ans; }
遞迴寫法
#include<bits/stdc++.h> using namespace std; typedef long long ll; ll quick_power(ll a, ll b, ll p){ //快速冪 if(b == 0) return 1 % p; ll res = quick_power(a,b>>1,p)%p; if(b&1) return (res * res % p) * a % p; else return res * res % p; } int main(){ ll a,b,p; cin>>a>>b>>p; ll ans = quick_power(a, b, p); cout<<ans; }
64位整數乘法
題目描述
求a乘b對p取模的值,其中1≤a,b,p≤1018
輸入
輸入3個long long型整數,a,b,p
輸出
輸出a*b%p的值
樣例輸入
250182048980811753
413715569939057660
133223633696258584
樣例輸出
19308689043391716
思路
與快速冪類似
\[b = \sum\limits_{i=0}^{k-1} c_i*2^i a*b = a*\sum\limits_{i=0}^{k-1} c_i*2^i = \sum\limits_{i=0}^{k-1} c_i*(a*2^i) \]而
\[a*2^i = a*2^{i-1}*2 \]同樣也可以用遞迴的思想
\[a*b = \left\{ \begin{aligned} & a*{\frac b2} + a*{\frac b2}&(b為偶數) \\ & a*{\frac {b-1}2} + a*{\frac {b-1}2}+a& (b為奇數)\\ \end{aligned} \right. \]程式碼
非遞迴寫法
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll quick_mul(ll a, ll b, ll p){ // 快速乘
ll ans = 0;
while(b){
if(b&1) ans = (ans + a) % p;
a = a*2%p;
b >>= 1;
}
return ans;
}
int main(){
ll a,b,p;
cin>>a>>b>>p;
ll ans = quick_mul(a,b,p);
cout<<ans;
}
遞迴寫法
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll quick_mul(ll a, ll b, ll p){ // 快速乘
if(b == 0) return 0;
ll res = quick_mul(a,b>>1,p) %p;
if(b & 1) return ((res+res)%p+a) %p;
else return (res+res)%p;
}
int main(){
ll a,b,p;
cin>>a>>b>>p;
ll ans = quick_mul(a,b,p);
cout<<ans;
}