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的更多相关文章
随机推荐
- 从零开始学Kotlin-泛型(8)
从零开始学Kotlin基础篇系列文章 与 Java 一样,Kotlin 也提供泛型,为类型安全提供保证,消除类型强转的烦恼. 泛型类的基本使用 泛型,即 "参数化类型",将类型参数 ...
- Gerrit 配置同步到多个仓库
1.修改replication.config文件 [remote "xxx"] projects = Yilule.Core.Service #aliyun仓库 url = git ...
- shell 命令 if [ -d filename] 判断文件
作者:曹毅涵 [ -a FILE ] 如果 FILE 存在则为真. [ -b FILE ] 如果 FILE 存在且是一个块特殊文件则为真. [ -c FILE ] 如果 FILE 存在且是一个字特殊 ...
- PostgreSQL之oracle_fdw安装与使用
目的介绍 现在项目开发遇到一个问题,就是需要从PostgreSQL中访问Oracle数据库 身为渣渣猿一脸懵逼.于是乎请教了公司的数据库方面的大牛韩工.告诉我用oracle_fdw 可以实现,但是在实 ...
- BZOJ3434 WC2014时空穿梭(莫比乌斯反演)
考虑枚举相邻点距离差的比例.显然应使比例值gcd为1以保证不重复统计.确定比例之后,各维坐标的方案数就可以分开考虑.设比例之和为k,则若坐标上限为m,该维坐标取值方案数即为Σm-ki (i=1~⌊m/ ...
- 【刷题】LOJ 6012 「网络流 24 题」分配问题
题目描述 有 \(n\) 件工作要分配给 \(n\) 个人做.第 \(i\) 个人做第 \(j\) 件工作产生的效益为 \(c_{ij}\) .试设计一个将 \(n\) 件工作分配给 \(n\) ...
- Ansible批量在远程主机执行命令
Ansible直接执行远程命令,不用ssh登陆交互执行. 如下: ansible all -i 192.168.199.180, -m shell -a "ifconfig" -u ...
- sqlplus执行startup出现ORA-00119,ORA-00132错误
安装好了oracle后,执行如下操作: 执行startup后出现如下错误: ORA-00119: invalid specification for system parameter LOCAL_LI ...
- codeforces906 D
题目链接:http://codeforces.com/contest/906/problem/D 题意: 给你n个数,再给你l~r,求%m 题解: 一开始不会 后来查到了欧拉降幂定理: 然后就会了 这 ...
- haoi2006_受欢迎的牛_Solution
Brief Solution: 强连通tarjan+压缩点+判断是否除了一个点,其它点都有出度 Detailed Solution: 把牛看成点若一个点b能到达点a,则b认为a受欢迎若所有的点都能到达 ...