引言
在RSA密碼中,當收到密文C時,可使用私鑰解開,計算公式爲
如果想讓你計算 應該如何用代碼實現?我們知道,在Java裏有大數類,Python依靠其強大的計算性能有些數據甚至可以直接計算。那麼在C/C++中應該如何處理?單獨用快速冪也會爆long long,我們可以採取快速冪調用快速乘進行取模的方法得到結果。
關於快速冪與快速乘的具體原理,可在此博客瞭解:快速冪 & 快速乘原理講解(模板)
1 原因分析
首先我們直接用快速冪計算引言中提到的公式:
不出意料,結果直接溢出。
2 快速冪取模(大數模冪模擬)
因爲數據實在是太大了,取模和開long long也沒辦法解決問題,於是可以對快速冪中的乘法運算
ans = (ans * base) % mod;
base = (base * base) % mod;
進行優化,改爲快速乘求結果
ll ksc(ll a, ll b, ll mod) {
ll ans = 0;
while(b) {
if(b & 1) {
ans = (ans + a) % mod;
}
a = (a + a) % mod;
b >>= 1;
}
return ans;
}
ll ksm(ll a, ll b, ll mod) {
ll ans = 1, base = a;
while(b) {
if(b & 1) {
//優化1
ans = ksc(ans, base, mod) % mod;
}
//優化2
base = ksc(base, base, mod) % mod;
b >>= 1;
}
return ans;
}
3 驗證
完整代碼:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 1001733993063167141;
ll ksc(ll a, ll b, ll mod) {
ll ans = 0;
while(b) {
if(b & 1) {
ans = (ans + a) % mod;
}
a = (a + a) % mod;
b >>= 1;
}
return ans;
}
ll ksm(ll a, ll b, ll mod) {
ll ans = 1, base = a;
while(b) {
if(b & 1) {
ans = ksc(ans, base, mod) % mod;
}
base = ksc(base, base, mod) % mod;
b >>= 1;
}
return ans;
}
int main() {
cout << "20190324 ^ 823816093931522017 = " << ksm(20190324, 823816093931522017, mod) << endl;
return 0;
}
運行結果:
可以看到數據溢出的問題得到解決,達到了大數模擬的效果。