http://poj.org/problem?id=2447
题目大意:
一个公钥密钥系统,给出C(密文),{E, N}公钥,要求破解出原文M
解题思路:
思路其实很简单。
1)由N破解出P和Q,得到T=(P-1)*(Q-1)
用PollardRho找出一个的质数因子(经过验证,不需要MillerRabin和二分配合,因为这个n肯定只有P和Q这两个非平凡因子)
PS:代码换过,不过注释掉的MillerRabin和二分部分继续留着,可以过POJ1811~
2)用扩展欧几里得求D
由于E和T是互质的,也就是gcd(E, T)=1。 (E * D) mod T = 1。用扩展欧几里得求解欧几里得方程E*D+T*K=gcd(E, T)=1即可。
最后用D=(D%T+T)%T处理了一下,也不确定是否必须。WA了无数次,这里写成%N了,坑爹啊!
3)pow_mod(C, D, N)
源代码:
其中很多模板都是用别人的,网上搜了几个源代码发现都TLE或者WA了,所以把自己这个拼凑的和尚的破袈裟贴一下……
#include <cstdio> #include <algorithm> #include <iostream> #include <limits.h> #include <ctime> using namespace std; #define int64_t __int64 #define TIME 100 int64_t gcd(int64_t a,int64_t b) { while(b) { int64_t t=a%b; a=b; b=t; } return a; } int64_t mul_mod(int64_t a, int64_t b, int64_t n){ int64_t tmp=0; while(b) { if(b&1){ tmp+=a; tmp%=n; } a<<=1; a%=n; b>>=1; } return tmp; } int64_t pow_mod(int64_t a, int64_t n,int64_t m) { int64_t p=1; for(int64_t i=1;i<=n;i<<=1) { if(i&n) p=mul_mod(p,a,m); a=mul_mod(a,a,m); } return p; } int64_t usr_abs(int64_t x){return x>0?x:-x;} //bool MillerRabin(int64_t n, int tries) //Return true if prime //{ // if(n==1) return false; // if(n==2||n==3) return true; // if(!(n&1)) return false; // int64_t d=n-1; // int s=0; // while(!(d&1)) {d>>=1;s++;} // while(tries--) // { // int64_t x=pow_mod(usr_abs((int64_t)rand())%(n-3)+2,d,n),y; // for(int j=0;j<s;j++) // { // y=mul_mod(x,x,n); // if(y==1&&x!=1&&x!=n-1) return false; // x=y; // } // if(x!=1) return false; // } // return true; //} int64_t PollardRho(int64_t n) //n shouldn't be prime { if(!(n&1)) return 2; while(true) { int64_t x=usr_abs((int64_t)rand())%n,y=x; int64_t c=usr_abs((int64_t)rand())%n; if(c==0||c==2) c=1; for(int i=1,k=2;;i++) { x=mul_mod(x,x,n); if(x>=c) x-=c; else x+=n-c; if(x==n) x=0; if(x==0) x=n-1; else x--; int64_t d=gcd(x>y?x-y:y-x,n); if(d==n) break; if(d!=1) return d; if(i==k) {y=x;k<<=1;} } } } //int64_t get_small(int64_t n) //{ // int64_t m, tmp1, tmp2; // if (MillerRabin(n, TIME)) return n; // m=PollardRho(n); // tmp1=get_small(m); // tmp2=get_small(n/m); // return tmp1<tmp2?tmp1:tmp2; //} //Solve ax+by=(a,b) void gcd_solve(int64_t a, int64_t b, int64_t &x, int64_t &y) { if (b==0){x=1;y=0;} else { gcd_solve(b,a%b,y,x); y-=a/b*x; } } int main() { int64_t C, E, N, P, Q, T, D, K, M; srand((unsigned int)time(NULL)); while (cin>>C>>E>>N) { //Get P and Q ==> T P=PollardRho(N); // P=get_small(N); Q=N/P; T=(P-1)*(Q-1); //Find D. Here D is a multiplicative inverse of E, modulo T. //ED mod T = 1 ==> ED+KT=1 而gcd(E,T)==1,即求解E*D+T*K = (E, T) gcd_solve(E, T, D, K); D=(D%T+T)%T; //M = (C ^ D) mod N cout<<pow_mod(C, D, N)<<endl; } return 0; }