sincerit 1211 RSA-拓展歐幾里得
1211 RSA
時間限制:2000/1000 MS(Java / Others)記憶體限制:65536/32768 K(Java /其他)
提交的總數:2894接受的提交內容:1974
問題描述
RSA是加密資料的最強大的方法之一。RSA演算法描述如下:
選擇兩個大素數整數p,q
計算n = p×q,計算F(n)=(p - 1)×(q - 1)
選擇整數e(1 < e <F(n)),使得gcd(e,F(n))= 1,e將是公鑰
計算d,使得d×e mod F(n)= 1 mod F(n),和d將是私鑰
你可以用這種方法加密資料:
C = E(m)= m^ e mod n
當你想解密資料時,使用這個方法:
M = D(c)= c^ d mod n
這裡,c是密碼字母的整數ASCII值,m是純文字字母的整數ASCII值。
現在給出p,q,e和一些密碼,你的任務是將密碼“翻譯”成純文字。
輸入
每個案例將以四個整數p,q,e,l開始,後跟一行加密。整數p,q,e,l將在32位整數的範圍內。密碼由l個由空格分隔的整陣列成。
產量
對於每種情況,只需在一行中輸出純文字。您可以假設純文字的正確結果是可視ASCII字母,您應該將它們輸出為可見的字母,它們之間沒有空白。
樣本輸入
101 103 7 11
7716 7746 7497 126 8486 4708 7746 623 7298 7357 3239
樣本輸出
I-LOVE-ACM。
解密的函式是D(c) = (c^d) % n; c是密碼字母的ASCII值,需要求的就是d,根據題意我們可以推出de - kfn = 1; 故使用拓展歐幾里得可以得打d和k,然後再解密就行了
https://blog.csdn.net/zhao5502169/article/details/70239344
/*擴充套件歐幾里得*/
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
void extgcd(ll &d, ll e, ll &k, ll fn) { // d*e - k*fn == 1
if (fn == 0) {
d = 1;
k = 0;
return;
}
extgcd(d, fn, k, e%fn); // fn e輾轉相處的情況
ll temp = d;
d = k;
k = temp - (e / fn) * k;
}
int main() {
ll p, q, e, l;
while (cin >> p >> q >> e >> l) {
ll d, k, fn = (p-1) * (q-1), n = p * q, code;
extgcd(d, e, k, fn);
while (d <= 0) d += fn;
for (int i = 0; i < l; i++) {
cin >> code;
ll ans = 1;
for (int j = 1; j <= d; j++) {
ans *= code;
ans %= n;
}
cout << char(ans);
}
cout << "\n";
}
return 0;
}
擴充套件歐幾里得
ax + by == 1,已知x, y求a,b
相似的還有一個費馬小定理:
假設p是質數,且gcd(a,p)=1,那麼 a(p-1)≡1(mod p)。
即:假如a是整數,p是質數,且a,p互質(即兩者只有一個公約數1),那麼a的(p-1)次方除以p的餘數恆等於1。
這個等式可以變形求出一個值但我忘了,其中用到了快速冪