Mr. Panda and Kakin (RSA 解密+解同余方程+O(1)快速乘)
题意:给了两个数\(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 }