描述ios
近日来勒索病毒的事件频繁发生,小Y对它的加密原理很是感兴趣,研究了一番相关知识以后,他就来给你看他的加密程序,并给你一段密文,和你炫耀说就算把程序给你看你也破解不出来。算法
你扫了一眼代码发现加密的公式为b=ae%m ,其中e 是质数。ui
进一步分析发现m=p∗q ,p 和q 都为质数,p!=q ,加密
做为一个计算机高手,你早就对加密算法烂熟于心,一眼就看出这个程序的算法和原理,找到了破解的方法,发现小Y疏忽在与给了你一个不够大的m 。spa
你知道解密的公式与加密对称,为a=bd%m 。code
可是你仍然没法心算解出这个d ,所以你须要借助计算机来将密文破解。blog
输入事件
第一行有一个整数T 表示数据组数。(T<=100 )
接着有T 组数据,每组数据两行。
第一行有四个数e 、p 、q 和n ,其中e 、p 、q 如题所描述,n 表示须要解密的数字序列长度。
第二行是须要解密的数字序列a1..an 。
1 < p ,q ,e <= 108 ,p 、q 、e 为质数且p!=q 。
$0<=a_i<=i<=n$)< br=""> 保证解密的结果即原数列的值小于min(p,q) 并大于等于0
1<=n<=100
保证m 有且仅有两个不一样的质因数p 和q ,而且必定存在一个题中描述的参数d 使得解密公式可以无损解密出全部0 ~min(p,q)−1 范围之间的数字。</M$。($1<=I<=N$)<>内存
输出get
对于每组数据输出一行,表示解密后的数字序列,数字之间以空格隔开。
样例输入1 复制
1 5 19 29 3 335 440 514
样例输出1
65 67 77
这题是RSA加密解密算法,比赛的时候自信写了,感受必定过,结果错了。。。。Orz还一直卡卡交不上去。(注意大整数溢出就行了)
涉及的内容大概就是计算逆元和快速幂,须要注意的是LL乘也会溢出,因此要处理乘。
#include <iostream> #include <stdio.h> using namespace std; typedef long long LL; LL e,p,q,n; int T; void extra_gcd(LL a, LL b, LL &x, LL &y, LL &d) { if(b == 0) { d = a; x = 1; y = 0; } else { extra_gcd(b, a%b, y, x, d); y -= (a/b) * x; } } LL multi_mod(LL a, LL n, LL mod) { LL ans = 0; while(n) { if(n & 1) { ans += a; if(ans > mod) ans -= mod; } n >>= 1; a <<= 1; if(a > mod) a-= mod; } return ans; } LL quick_mod(LL a,LL n,LL mod) { LL ans = 1; while(n) { if(n & 1) ans = multi_mod(ans, a, mod); a = multi_mod(a, a, mod); n >>= 1; } return ans; } int main() { scanf("%d", &T); while(T--) { scanf("%lld%lld%lld%lld",&e,&p,&q,&n); LL m=(p-1)*(q-1); LL y = p*q; LL d, o, l; extra_gcd(e, m, d, o, l); d = ((d%m)+m)%m; for(LL i = 0; i < n; i++) { LL tmp; scanf("%lld", &tmp); tmp %= y; if(i) printf(" "); printf("%lld",quick_mod(tmp,d,y)); } printf("\n"); } return 0; }