P4358 [CQOI2016] 密钥破解

显然只需要对 \(N\) 进行质因数分解即可求出 \(r , d\)
那么我们只需要用Pollard-Rho算法即可
然而发现不会写

#include<bits/stdc++.h>
using namespace std;
#define int __int128
int read(){
    int num=0,flag=1;char c;
    while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
    while(c>='0'&&c<='9')num=(num<<3)+(num<<1)+(c^48),c=getchar();
    return num*flag;
}
void write(int x){
	if(x>=10)write(x/10);
	putchar(x%10+'0');
}
int abs(int x){
	return x>0?x:-x;
}
int f(int x,int c,int mod){
	return (x*x%mod+c)%mod;
}
int gcd(int a,int b){
	return b?gcd(b,a%b):a;
}
int ksm(int a,int b,int mod){
	int res=1;
	while(b>0){
		if(b&1)res=res*a%mod;
		a=a*a%mod;
		b>>=1;
	}
	return res;
}
bool mr(int x,int b){
	int k=x-1;
	while(k>0){
		int cur=ksm(b,k,x);
		if(cur^1 && cur^x-1)return 0;
		if((k&1)==1 || cur==x-1)return 1;
		k>>=1;
	}
	return 1;
}
bool prime(int x){
	if(x==46856248255981ll || x<2)return 0;
	if(x==2 || x==3 || x==7 || x==61 || x==24251)return 1;
	return mr(x,2) && mr(x,61);
}
int pollard_rho(int x){
	int s=0,t=0,c=1ll*rand()%(x-1)+1,val=1;
	for(int i=1;;i<<=1,s=t,val=1){
		for(int j=1;j<=i;j++){
			t=f(t,c,x);
			val=val*abs(t-s)%x;
			if(j%127==0){
				int d=gcd(val,x);
				if(d>1) return d;
			}
		}
		int d=gcd(val,x);
		if(d>1) return d;
	}
}
int e,n,c;
int p,q,r;
int x,y;
void exgcd(int a,int b){
    if(!b) x=1,y=0;
    else{
        exgcd(b,a%b);
        int k=x; x=y;
    	y=k-a/b*y;
    }
}
signed main(){
	e=read();n=read();c=read();
	p=n;
	while(p>=n)p=pollard_rho(n);
	q=n/p;
	r=(p-1)*(q-1);
	exgcd(e,r);x=(x%r+r)%r;
	write(x);putchar(' ');write(ksm(c,x,n));putchar('\n');
	return 0;
}

(逆元别用费马小定理,我调了半天)
感觉这题有点板子

posted @ 2023-08-23 14:17  Kent530  阅读(43)  评论(0编辑  收藏  举报