[CQOI2016]密钥破解

洛咕

题意:对于整数N((N<=2^{62})),求出两个不同的质数p和q,使得(N=p*q);令(r=(p-1)*(q-1)),给定整数e(e<r且e,r互质),求出整数d,使得(e*d≡1(mod r));给定整数c,求出整数n使得(c*d≡n(mod N)).

Pollard-Rho算法扩展欧几里得算法的模板题.

#include<bits/stdc++.h>
#define rg register
#define LL long long 
using namespace std;
inline LL read(){
    rg LL s=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
    return s*w;
}
LL e,N,c;
inline LL ksc(LL a,LL b,LL c){
    rg LL cnt=0;
    while(b){
		if(b&1)cnt=(cnt+a)%c;
		a=(a+a)%c;
		b>>=1;
    }
    return cnt%c;
}//龟速乘,防止乘的时候爆long long
inline LL ksm(LL a,LL b,LL c){
    rg LL cnt=1;
    while(b){
		if(b&1)cnt=ksc(cnt,a,c);
		a=ksc(a,a,c);
		b>>=1;
    }
    return cnt%c;
}
inline LL gcd(LL a,LL b){
    if(b==0)return a;
    return gcd(b,a%b);
}
inline LL pr(LL n){
    rg LL x,y,cs,sum,i,j,d;
    while(1){
		y=x=rand()%n;cs=rand()%n;
		sum=1;i=0;j=1;
		while(++i){
	    	x=ksc(x,x,n)+cs;
	    	sum=ksc(abs(y-x),sum,n);
	    	if(x==y||sum==0)break;
	    	if(i%127==0||i==j){
				d=gcd(sum,n);
				if(d>1&&d!=n)return d;
				if(i==j)y=x,j<<=1;
	    	}
		}
    }
}
inline 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;
}
int main(){
    e=read();N=read();c=read();
    LL p=pr(N),r=1LL*(p-1)*(N/p-1);
    LL x,y;exgcd(e,r,x,y);
    LL d=(x%r+r)%r,n=ksm(c,d,N);
    printf("%lld %lld
",d,n);
    return 0;
}

原文地址:https://www.cnblogs.com/PPXppx/p/10542830.html