https://codeforc.es/gym/102055/problem/K
K - Mr. Panda and Kakin
题意
给出 n , c n, c n,c, n = p ∗ q n = p*q n=p∗q, p p p和 q q q是x附近相邻的两个质数, c = f 2 30 + 3 m o d n c = f^{2^{30}+3} \ mod\ n c=f230+3 mod n。求出 f f f的值。
题解
RSA解密,令
e
=
2
30
+
3
e = {2^{30}+3}
e=230+3。令
r
=
(
p
−
1
)
(
q
−
1
)
r = (p-1)(q-1)
r=(p−1)(q−1)
d
∗
e
m
o
d
r
≡
1
d*e\ mod \ r \equiv 1
d∗e mod r≡1
c
=
f
e
m
o
d
n
c = f^e \ mod\ n
c=fe mod n
f
=
c
d
m
o
d
n
f = c^d \ mod \ n
f=cd mod n
可以暴力在sqrt(n)附近寻找p,q,因为两个素数差距不会很大。
已知e和r,可以解同余方程
e
x
+
r
y
=
1
ex+ry=1
ex+ry=1
得出d的值。
即可以算出f的值。
此题需要用O(1)快速乘才能通过。
代码
#include <bits/stdc++.h>
using namespace std;
#define FOR0(a,b) for(int i = a; i < b; ++i)
#define FORE(a,b) for(int i = a; i <= b; ++i)
typedef long long ll;
typedef pair<int,int> pii;
inline void add(ll &a,ll b,ll c){a+=b;if(a>=c)a-=c;}
#define ld long double
inline ll mul(ll a,ll b,ll c){return (a*b-(ll)((ld)a*b/c)*c+c)%c;}
ll exgcd(ll a, ll b, ll& x, ll &y) {
if(b == 0) {
x = 1; y = 0;
return a;
}
ll d = exgcd(b,a%b,y,x);
y -= a/b*x;
return d;
}
inline ll pw(ll x, ll n, ll mod) {
ll ret = 1;
while(n) {
if(n&1) ret = mul(ret,x,mod);
x = mul(x,x,mod);
n >>= 1;
}
return ret;
}
int main() {
int T;
scanf("%d", &T);
int ca = 0;
ll a,b,x,y;
a = (1<<30)+3;
while(T--) {
ll n,c;
scanf("%lld%lld", &n, &c);
ll p = sqrt(n);
while(n%p != 0) p--;
ll q = n/p;
ll r = (p-1)*(q-1);
b = r;
exgcd(a,b,x,y);
x = ((x%b)+b)%b;// 保证是正数
ll f = pw(c,x,n);
printf("Case %d: %lld\n",++ca,f);
}
return 0;
}
蓝桥省赛 RSA解密

题解
d
∗
e
m
o
d
r
≡
1
d*e\ mod \ r \equiv 1
d∗e mod r≡1
本题的d正好与r互质,所以可以算出d的逆元。
e
m
o
d
r
≡
d
−
1
e\ mod \ r \equiv d^{-1}
e mod r≡d−1
对
X
=
C
e
m
o
d
n
X=C^e\ mod \ n
X=Ce mod n
进行欧拉降幂
X
=
C
e
m
o
d
r
m
o
d
n
X=C^{e\ mod \ r} \ mod \ n
X=Ce mod r mod n
替换指数。
X
=
C
d
−
1
m
o
d
n
X=C^{d^{-1}} \ mod \ n
X=Cd−1 mod n
即可在2ms之内求出X。需要注意,由于r不是素数,所以不能直接用费马小定理的快速幂求。可以采用扩展欧几里得求d的逆元
#include <bits/stdc++.h>
using namespace std;
#define FOR0(a,b) for(int i = a; i < b; ++i)
#define FORE(a,b) for(int i = a; i <= b; ++i)
typedef long long ll;
typedef pair<int,int> pii;
#define ld long double
inline ll mul(ll a,ll b,ll c){return (a*b-(ll)((ld)a*b/c)*c+c)%c;}
ll pw(ll x, ll n, ll c) {
ll ret = 1;
while(n) {
if(n&1) ret = mul(ret,x,c);
x = mul(x,x,c);
n >>= 1;
}
return ret;
}
ll exgcd(ll a, ll b, ll& x, ll& y) {
if(b == 0) {
x = 1; y = 0;
return a;
}
ll d = exgcd(b,a%b,y,x);
y -= a/b*x;
return d;
}
ll inv(ll a, ll n) {
ll x,y;
ll d = exgcd(a,n,x,y);
return d == 1 ? (x+n)%n:-1;
}
int main() {
clock_t start,end;
start = clock();
ll n = 1001733993063167141;
ll d = 212353;
ll C = 20190324;
ll p = sqrt(n);
while(n%p != 0) {
p--;
}
ll q = n/p;
// cout << p << " "<< q<<endl;
ll phi = (p-1)*(q-1);
// cout << "gcd:" <<__gcd(phi,d) << endl;
ll invd = inv(d,phi);
// cout << invd << endl;
ll X = pw(C,invd,n);
cout << X << endl;
end = clock();
cout<<(double)(end-start)/CLOCKS_PER_SEC*1000<<"ms"<<endl;
return 0;
}
263



被折叠的 条评论
为什么被折叠?



