https://www.luogu.com.cn/problem/P2626
本来思路很简单。
但是我 。。了一个 n < = 1 e 8 , 模 数 < = 1 e 18 n<=1e8,模数<=1e18 n<=1e8,模数<=1e18都能切的冗长代码。
竟然没有他们的快??。 。咕了。
注意一下的是听说pollard_rho的常数调成127会比较优秀
。
#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;
}