BZOJ4522 [Cqoi2016]密钥破解

数论模板集合.

用到了快速乘,快速幂,exgcd,Pollard_Rho因数分解.

这题乘法各种爆long long,只要有一个地方不加快速乘就wa或者死循环.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<string>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<iomanip>
using namespace std;
#define ll long long
#define db double 
#define up(i,j,n) for(ll i=j;i<=n;i++)
#define pii pair<ll,ll>
#define uint unsigned ll
#define FILE "dealing"
ll read(){
	ll x=0,f=1,ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
	return x*f;
}
template<class T> bool cmax(T& a,T b){return a<b?a=b,true:false;}
template<class T> bool cmin(T& a,T b){return a>b?a=b,true:false;}
const ll maxn=1010000;
ll p,q,c,e,d,n,N,r;
void exgcd(ll a,ll b,ll& d,ll& x,ll& y){
	if(b==0){x=1;y=0;d=a;return;}
	exgcd(b,a%b,d,x,y);
	ll t=x;
	x=y;
	y=t-a/b*y;
}
inline ll mul(ll x,ll y,ll mod){
	ll tmp=(x*y-(ll)((long double)x/mod*y+1.0e-8)*mod);
	return tmp<0 ? tmp+mod : tmp;
}

ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
void pholl(ll n){
	ll c=rand()+3;
	while(true){
		ll x1=1,x2=1,k=2,i=1;
		while(true){
			x1=(mul(x1,x1,n)+c)%n;
			ll d=gcd(abs(x1-x2),n);
			if(d>1&&d<n){
				p=d,q=n/d;
				return;
			}
			if(x1==x2)break;
			if(++i==k)k<<=1,x2=x1;
		}
		c++;
	}
}
ll fast(ll a,ll b,ll mod){
	ll ans=1;
	for(;b;b>>=1,a=mul(a,a,mod))if(b&1)ans=mul(ans,a,mod);
	return ans;
}
int main(){
	freopen(FILE".in","r",stdin);
	freopen(FILE".out","w",stdout);
	e=read(),N=read(),c=read();
	pholl(N);
	r=(p-1)*(q-1);
	ll w,m;
	exgcd(e,r,w,d,m);
	d=(d%r+r)%r;
	n=fast(c,d,N);
	printf("%lld %lld\n",d,n);
	return 0;
}

  

posted @ 2017-03-14 21:30  CHADLZX  阅读(198)  评论(0编辑  收藏  举报