[PE182]RSA encryption

https://projecteuler.net/problem=182

题意:

找出满足下列条件的所有$e$ 的和,

- $1 < e < \varphi \left( {1009,3643} \right)$
- $gcd(e,φ)=1$
- 满足${m^e} \equiv m{\rm{ }}\bmod {\rm{ }}n$ 的$m$的个数最小

解答:

这道题最重要的就是解决这个问题:

${m^e} \equiv m{\rm{ }}\bmod {\rm{ }}n$ 中$e$确定时,$m$的取值的个数。

由于n是合数,且 $n = p*q$ ,所以先考虑${m^e} \equiv m{\rm{ }}\bmod {\rm{ }}p$ 和 ${m^e} \equiv m{\rm{ }}\bmod {\rm{ }}q$ ,

$m({m^{e - 1}} - 1) \equiv 0{\rm{ }}\bmod {\rm{ }}p$ , $p$ 是质数

- $m==0$ ,恒成立
- $m!=0$ ,${m^{e - 1}} \equiv 1\bmod {\rm{ }}p$

考虑 ${a^b} \equiv 1\bmod p$ ,$a$ 、$p$ 互素,此式中$b$确定时,$a$的个数

因为$p$ 为素数,所以必存在原根$r$ ,使得$ a= {r^k}$ ,

${r^{kb}} = 1{\rm{ }}\bmod {\rm{ }}p$

这里很容易联想到关于${a^k}\bmod {\rm{ }}p$的阶那个公式,

$ord({r^b}) = \frac{{\varphi (p)}}{{(\varphi (p),b)}},(r,p) = = 1$

变换一下位置,

$(\varphi (p),b) = \frac{{\varphi (p)}}{{ord({r^b})}},(r,p) = = 1$

${r^{ord({r^b})}}$ ,${r^{2ord({r^b})}}$ ,...,${r^{(\varphi (p ),b )ord({r^b})}}$就是使上式成立的$a$的可能取值,

所以左边就是解的个数。

所以最初的解为$\gcd (\varphi (p),b) = \gcd (p - 1,b)$

回到上面,还有$m==0$ 的情况,

所以解为$\gcd (\varphi (p),b)+1 = \gcd (p - 1,b)+1$

再看如何解决模数不为质数的问题,这里 就需要用到中国剩余定理,根据中国剩余定理,每一对$p$ 和 $q$ ,就会产生一个解,依据乘法原理,所以最后的解为$[\gcd (p - 1,e - 1) + 1]*[\gcd (q - 1,e - 1) + 1]$

接下来:就是枚举$e$ 的问题了

- 直接进行暴力

- 观察$e$,因为$\gcd ((p - 1)(q - 1),e ) = = 1$ ,故$e$ 为奇数,$e-1$ 为偶数, $\gcd (e - 1,p - 1) > = 2$ ,

$\gcd (e - 1,q - 1) > = 2$ ,这里确定了两个gcd的下界的最小值,而且显然这两个下界在枚举$e$ 的过程中是可以取到的,所以这里可以直接判断最小的情况。

复杂度:$O(n\log n)$ ,其中$logn$ 是辗转相除的复杂度,证明见维基百科。

代码1:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const ll inf=1<<30;
 5 ll p=1009,q=3643,factor[4070000];
 6 ll n=q*p,phi=(p-1)*(q-1),mi=inf,ans;
 7 int main(){
 8     for(ll i=2;i<phi;++i)    if(__gcd(i,phi)==1) factor[i]=(__gcd(i-1,p-1)+1)*(__gcd(i-1,q-1)+1),mi=min(mi,factor[i]);
 9     for(ll i=2;i<phi;++i)    if(factor[i]==mi)    ans+=i;
10     printf("%lld\n",ans);
11 }

 

代码2:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const ll inf=1<<30;
 5 ll p=1009,q=3643;
 6 ll n=q*p,phi=(p-1)*(q-1),ans;
 7 int main(){
 8      for(ll i=3;i<phi;++i)    if(__gcd(i,phi)==1&&__gcd(i-1,q-1)==2&&__gcd(i-1,p-1)==2) ans+=i;
 9      printf("%lld\n",ans);
10 }

 

posted @ 2017-09-04 23:12  Elpsywk  阅读(333)  评论(0编辑  收藏  举报