蓝桥杯rsa解密
需要知识点
快速乘、快速加、扩展欧几里得原理
模板
快速乘
ll qkc(ll a,ll b){
ll ans = 0;
while(b)
{
if(b&1) ans = (ans+a)%n;
a=(a+a)%n;
b /=2;
}
return ans;
}
快速幂
ll qkm(ll a,ll b){
ll ans = 1;
while(b)
{
if(b&1) ans =qkc(ans,a);
a = qkc(a,a);
b/=2;
}
return ans;
}
扩展欧几里德
ll exgcd(ll a,ll b,ll &x,ll &y)
{
if(!b)
{
x=1,y=0;
return a;
}
ll d = exgcd(b,a%b,y,x);
y -= a/b*x;
return d;
}
解题
题目
题目没有限制是那两个素数,所以硬筛两个p,q即可,令b = (q-1)*(p-1)
已知b,a(即d) 可得方程 de mod b = 1 => de -k*b = 1;
用扩展欧几里得可求二元一次方程的可行解,可求得e = x,k = y
x可能小于0,用b余一下e = (x+b)%b,这样才能用于指数
结果即是c的e次方余n
题解代码
//by InsiApple
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define rep(i,n,m) for(int i=(n);i<=(m);i++)
#define per(i,n,m) for(int i=(m);i>=(n);i--)
#define all(a) a.begin(), a.end()
#define pw(x) (1ll<<(x))
#define endl "\n"
#define Mod 100000000
const int N = 1e6+10;
ll n=1001733993063167141;
ll d=212353;
ll C=20190324;
ll p,q,e;
ll qkc(ll a,ll b){
ll ans = 0;
while(b)
{
if(b&1) ans = (ans+a)%n;
a=(a+a)%n;
b /=2;
}
return ans;
}
ll qkm(ll a,ll b){
ll ans = 1;
while(b)
{
if(b&1) ans =qkc(ans,a);
a = qkc(a,a);
b/=2;
}
return ans;
}
ll exgcd(ll a,ll b,ll &x,ll &y)
{
if(!b)
{
x=1,y=0;
return a;
}
ll d = exgcd(b,a%b,y,x);
y -= a/b*x;
return d;
}
int main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
for(q = 2;q<n;q++)
if(n%q==0){
p = n/q;
break;
}
ll k = (p-1)*(q-1);
ll x,y;
exgcd(d,(p-1)*(q-1),x,y);
q = (p-1)*(q-1);
x = (x+q)%q;
//cout<<x<<endl;
cout<<qkm(C,x);
return 0;
}
本文来自博客园,作者:InsiApple,转载请注明原文链接:https://www.cnblogs.com/InsiApple/p/16001731.html