#矩阵乘法快速递推+pollard rho+miller rabin算法# [luogu 2626] 斐波那契数列(升级版)

题目

https://www.luogu.com.cn/problem/P2626


解题思路

本来思路很简单。
但是我 。。了一个 n < = 1 e 8 , 模 数 < = 1 e 18 n<=1e8,模数<=1e18 n<=1e8,<=1e18都能切的冗长代码。
竟然没有他们的快??。 。咕了。

注意一下的是听说pollard_rho的常数调成127会比较优秀


code

#pragma GCC target("avx")
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")

#include
#include
#define WYC 2147483648
#define w 2 
#define rep(i,x,y) for(register long long i=x;i

#include
#include
#define rr register 
#define mytz __builtin_ctzll
const long long Times=10,N=50; 

using namespace std; 

typedef long long LL; 

LL ff[w],af[w][w]; 
inline void mull(){
	LL c[w][w]={{0,0},{0,0}}; 
	rep(i,0,w) rep(j,0,w) rep(k,0,w)
	 c[i][j]=(c[i][j]+af[i][k]*af[k][j])%WYC; 
	memcpy(af,c,sizeof(c)); 
}
inline void mul(){
	LL c[w]={0,0};  
	rep(j,0,w) rep(k,0,w)
	 c[j]=(c[j]+ff[k]*af[k][j])%WYC; 
	memcpy(ff,c,sizeof(c));
}



int ct,fac[N]; 
inline int gcd(int a,int b){
    if(!a) return b;
    if(!b) return a;
    register int t=mytz(a|b) ;
    a>>=mytz(a) ;
    do{
        b>>=mytz(b) ;
        if(a>b){int t=b;b=a,a=t;}
        b-=a;
    }while(b); 
    return a<<t;
}
inline int multi(int a,int b,int m){
	int ans=0; a%=m; 
	for(;b;b>>=1,a=(a+a)%m)	if (b&1) ans=(ans+a)%m; 
	return ans; 
}
inline int quick_mod(int a,int b,int m){
	int ans=1; a%=m;
	for(;b;b>>=1,a=multi(a,a,m)) if (b&1) ans=multi(ans,a,m); 
	return ans; 
}
inline bool Miller_Rabin(int n){
	if (n==2) return true; 
	if (n<2||!(n&1)) return false; 
	int m=n-1; int k=0; 
	for (;(m&1)==0;m>>=1) k++; 
	for (rr int i=0;i<Times;i++){
		int a=rand()%(n-1)+1,x=quick_mod(a,m,n),y=0; 
		for(rr int j=0;j<k;j++){
			y=multi(x,x,n); 
			if (y==1&&x!= 1&&x!=n-1) return false; 
			x=y; 
		}
		if (y!=1) return false; 
	}
	return true; 
}
inline int pollard_rho(int n,int c){
	int i=1,k=2,x=rand()%(n-1)+1,y=x; 
	while (true){
		i++; 
		x=(multi(x,x,n)+c)%n; 
		int d=gcd((y-x+n)%n,n); 
		if (1<d&&d<n) return d; 
		if (y==x) return n; 
		if (i==k) y=x,k<<=1;
	}
}
inline void find(int n,int c){
	if (n==1) return; 
	if (Miller_Rabin(n)){fac[ct++]=n; return;}
	int p=n,k=c; 
	while (p>=n) p=pollard_rho(p,c--); 
	find(p,k),find(n/p,k); 
}


int main(){
	LL n; 
	scanf("%lld",&n);
	ff[0]=0; ff[1]=1; 
	af[0][0]=0; af[0][1]=1; af[1][0]=1; af[1][1]=1; 
	for(;n;mull(),n>>=1) if (n&1) mul(); 
	n=ff[0]%WYC; n=(int)n; printf("%d=",n); 
	
	
	if (Miller_Rabin(n)) {printf("%d",n); } else {
		ct=0; find(n,120);/*127*/ 
		sort(fac,fac+ct); 
		for(int i=0;i<ct-1;i++) printf("%d*",fac[i]); 
		printf("%d",fac[ct-1]);
	}
	
	return 0; 
}

你可能感兴趣的:(随机算法,数论(数学),矩阵乘法(快速幂加速递推))