poj2447
题意:两个素数P,Q。N=P*Q; T=(P-1)*(Q-1); (E*D)mod T = 1; (0<=D<T)。E与T互质,公钥是{E,N},私钥是{D,N}。原始信息M的加密过程为C=(M^E)mod N; 解密过程为 M=(C^D)mod N;("^"表示幂) 现在给出C,E,N(<2^62)。求M。
分析:先通过N分解求P,Q(pollard-rho+Miller-rabin)。通过P,Q求T,通过(E*D)mod T = 1求D(扩展欧几里德),通过M=(C^D)mod N求M。
如何使用扩展欧几里德呢,
(E*D)mod T = 1 <=> (E*D) = 1 + k*T <=> E*(D*g) + T*[(-k)*g] = g(g是T和E的最大公约数gcd(T,E))。
不过这道题好像不用这么麻烦,因为E和T互质,所以g=1。
这样就变成了a*x+b*y=gcd(a,b)的形式了。
pollard-rho和Miller-rabin算法参见poj1811解题报告 http://www.cnblogs.com/rainydays/archive/2011/09/01/2162049.html
扩展欧几里德算法参见poj1061解题报告 http://www.cnblogs.com/rainydays/archive/2013/07/19/3201618.html
#include <cstdio>
#include <cstdlib>
#include <ctime>
using namespace std; typedef long long LL;
#define maxn 10000
const int S=; LL factor[maxn];
int tot; LL muti_mod(LL a,LL b,LL c){ //返回(a*b) mod c,a,b,c<2^63
a%=c;
b%=c;
LL ret=;
while (b){
if (b&){
ret+=a;
if (ret>=c) ret-=c;
}
a<<=;
if (a>=c) a-=c;
b>>=;
}
return ret;
} LL pow_mod(LL x,LL n,LL mod){ //返回x^n mod c ,非递归版
if (n==) return x%mod;
int bit[],k=;
while (n){
bit[k++]=n&;
n>>=;
}
LL ret=;
for (k=k-;k>=;k--){
ret=muti_mod(ret,ret,mod);
if (bit[k]==) ret=muti_mod(ret,x,mod);
}
return ret;
} bool check(LL a,LL n,LL x,LL t){ //以a为基,n-1=x*2^t,检验n是不是合数
LL ret=pow_mod(a,x,n),last=ret;
for (int i=;i<=t;i++){
ret=muti_mod(ret,ret,n);
if (ret==&& last!=&& last!=n-) return ;
last=ret;
}
if (ret!=) return ;
return ;
} bool Miller_Rabin(LL n){
LL x=n-,t=;
while ((x&)==) x>>=,t++;
bool flag=;
if (t>=&& (x&)==){
for (int k=;k<S;k++){
LL a=rand()%(n-)+;
if (check(a,n,x,t)) {flag=;break;}
flag=;
}
}
if (!flag || n==) return ;
return ;
} LL gcd(LL a,LL b){
if (a==) return ;
if (a<) return gcd(-a,b);
while (b){
LL t=a%b; a=b; b=t;
}
return a;
} LL Pollard_rho(LL x,LL c){
LL i=,x0=rand()%x,y=x0,k=;
while (){
i++;
x0=(muti_mod(x0,x0,x)+c)%x;
LL d=gcd(y-x0,x);
if (d!=&& d!=x){
return d;
}
if (y==x0) return x;
if (i==k){
y=x0;
k+=k;
}
}
} void findfac(LL n){ //递归进行质因数分解N
if (!Miller_Rabin(n)){
factor[tot++] = n;
return;
}
LL p=n;
while (p>=n) p=Pollard_rho(p,rand() % (n-) +);
findfac(p);
findfac(n/p);
} void gcdExtend(long long a,long long b,long long &d,long long &x,long long &y)
{
if(!b) {d=a;x=;y=;return;}
gcdExtend(b,a%b,d,y,x);
y-=a/b*x;
} int main()
{
LL C, E, N, T, M, D;
LL x, y, d;
while (~scanf("%lld%lld%lld", &C, &E, &N))
{
tot = ;
findfac(N);
T = (factor[] - ) * (factor[] - );
gcdExtend(E, T, d, x, y);
D = (x % T + T) % T;
M = pow_mod(C, D, N);
printf("%lld\n", M);
}
return ;
}
poj2447的更多相关文章
随机推荐
- 常用的sublime text 3插件(很爽哦)
个人比较懒,平时喜欢用webstorm,但是因为webstorm打开实在太慢了,并且太看设备,所以本人编辑简单的文件依然会选择使用sublime,虽然网上有很多关于此类插件的分享了,但是感觉都是片段, ...
- 从web启动winform程序
最近有个客户提出想从网站上启动一个客户端的程序,研究了下,实现方法如下: 1. 注入注册表 try { string appPath ...
- 洛谷P3302 森林
题意:给定森林,可以把两棵树连起来或者询问链上第k大. 解:启发式合并. 我一开始想到了启发式合并但是发现这样做之后一棵子树就不是一段连续的区间了,那就不能子树xxx了,很迷惘. 后来看了题解发现本来 ...
- 详解掩膜mask
什么是掩膜(mask) 数字图像处理中的掩膜的概念是借鉴于PCB制版的过程,在半导体制造中,许多芯片工艺步骤采用光刻技术,用于这些步骤的图形“底片”称为掩膜(也称作“掩模”),其作用是:在硅片上选定的 ...
- mysql新版本问题
异常错误:Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.c ...
- eos节点启动源码分析
在eos源码目录中programs/nodeos/main.cpp文件里,为节点启动的主函数main函数内部做了两件事1 初始化 application if(!app().initialize< ...
- sqlserver收缩日志的几种方式
sqlserver收缩日志的几种方式 [sql] --参考 压缩日志及数据库文件大小 /*--特别注意 请按步骤进行,未进行前面的步骤,请不要做后面的步骤 否则可 ...
- 自己写的一个Vue
下面这里是我自己写的一个小型的vue,原理就是proxy: //Proxy天生没有prototype,因此要加上,不然extends会报错 Proxy.prototype = Proxy.protot ...
- Spark记录-Scala语法基础
参考:http://docs.scala-lang.org/cheatsheets/index.html.http://docs.scala-lang.org/.http://www.scala-la ...
- nginx配置伪静态
最近做门户网站,使用了的nginx重写规则 项目目录下写好 nginx.conf文件 然后在打开nginx配置文件,在server引入对应的重写规则的文件就可以了 当然直接写在配置里面 locatio ...