Mr. Panda and Kakin (RSA 解密+解同余方程+O(1)快速乘)

Mr. Panda and Kakin

题意:给了两个数\(n,c\),\(n=p*q\),\(p\)和\(q\)是一个未知的数\(x\)前后的两个质数,\(c = f^{2^{30}+3}\ mod\ n\)。让求\(f\)的值。

题解:参考大佬博客

我们先来了解一下\(RSA解密\)

再回头来看这个式子\(c = f^{2^{30}+3}\ mod\ n\),让求\(f\)是不是就是给了原来的数字,让求密文?

对应着上面的,我们就有设\(e = 2^{30}+3\),那么\(c = f^{e}\ mod\ n\),\(f = c^{d}modn\),到这儿我们就发现了,我们不知道\(d\)是什么;

根据上面\(RSA\)加密的描述可以知道\(\left ( d*e\right ) mod \left [ \left ( p-1\right )\left ( q-1\right )\right ]\equiv 1\)

设\(r = \left ( p-1\right )\left ( q-1\right )\),就是\(\left ( d*e\right )mod r \equiv 1\)

求解方程 \(a*x\equiv b\left ( mod n\right )x未知\) 相当于求解方程 \(ax+ny=b,所以这里我们相当于求解方程ex+ry=1\),解线性同余方程即可得出\(d\)。

问题又来了\(r\)我们不知道是啥......

看上面我们设的\(r = \left ( p-1\right )\left ( q-1\right )\),那么求\(r\)的问题变成了求\(p,q\)的问题,\(n=p*q\),\(n\)题目已经给了,我们可以在\(sqrt\left ( n\right )\)附近找\(p,q\)

综上所述,我们先求出\(p,q\),再求出\(d\),最后求出\(f\)

 AC_Code:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 typedef long double ld;
 5 #define endl '\n'
 6 const int inf=0x3f3f3f3f;
 7 const int maxn=2e5+10;
 8 const ll maxm=1073741827;
 9 
10 
11 ll n,c;
12 
13 ll exgcd(ll a,ll b,ll &x,ll &y){
14     if( b==0 ){
15         x=1;y=0;
16         return a;
17     }
18     ll d=exgcd(b,a%b,y,x);
19     y-=a/b*x;
20     return d;
21 }
22 
23 ll qpow(ll a,ll b,ll mod){
24     ll res=1;
25     while( b ){
26         if( b&1 ) res=res*a%mod;
27         a=a*a%mod;
28         b>>=1;
29     }
30     return res;
31 }
32 
33 ll mul(ll a,ll b,ll c){
34     return (a*b-(ll)((ld)a*b/c)*c+c)%c;
35 }
36 
37 ll pw(ll x, ll n, ll mod) {
38     ll ret = 1;
39     while(n) {
40         if(n&1) ret = mul(ret,x,mod);
41         x = mul(x,x,mod);
42         n >>= 1;
43     }
44     return ret;
45 }
46 
47 int main()
48 {
49     int T,cas=0; scanf("%d",&T);
50     while( T-- ){
51         scanf("%lld%lld",&n,&c);
52 
53         ll p=sqrt(n);
54         while( n%p!=0 ) p--;
55         ll q=n/p;
56         ll r=(p-1)*(q-1);
57 
58         ll a,b,x,y;
59         a=(1<<30)+3;
60         b=r;
61         exgcd(a,b,x,y);
62         x = ((x%b)+b)%b;    //保证是整数
63 //        ll f=qpow(c,x,n);   //错,因为c,n都太大了这样直接快速幂的话中间会有溢出
64         ll f=pw(c,x,n);     //要用这个O(1)的快速乘
65         printf("Case %d: %lld\n",++cas,f);
66     }
67     return 0;
68 }

 

posted @ 2020-08-12 21:03  swsyya  阅读(417)  评论(0编辑  收藏  举报

回到顶部