P4718Pollard-Rho算法
Posted shxnb666
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P4718Pollard-Rho算法相关的知识,希望对你有一定的参考价值。
题面
https://www.luogu.org/problem/P4718
题解
一开始傻逼爆了,直接开的$int$,但是这道题大多数地方要用$LL$。
首先$gcd(|a-b|,n)$是不一定为质数的,必须再递归用一次$Pollard-Rho$,也求出它的最大质因子(所以最好不要把$n$开成全局变量)。
结果交上去全$T$了的,后来开$int128$就变成$94$分了。
注意快速$gcd$算法(更相减损术)的卡常。
#pragma GCC optimize(2) #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define LLL __int128 #define LL long long #define ri int using namespace std; LL n,c; const int p[10]=2,3,5,7,11,13,17,19,61,24251; const LL q[350]=...; const int ans[350]=...; LL mul(LL a,LL b,LL n) return ((LLL)a*b)%n; LL pow(LL a,LL b,LL n) LL ret=1; for (;b;b>>=1,a=mul(a,a,n)) if (b&1) ret=mul(ret,a,n); return ret; LL f(LL x,LL n) return (mul(x,x,n)+c)%n; #define ctz __builtin_ctzll LL gcd(LL a,LL b) if(!a) return b; if(!b) return a; int t=ctz(a|b); a>>=ctz(a) ; do b>>=ctz(b) ; if(a>b) swap(a,b); b-=a; while(b); return a<<t; LL ads(LL a) return (a>0)?a:-a; bool prime(LL n) if (n==1) return 1; for (ri i=0;i<10;i++) if (n==p[i]) return 1; for (ri i=0;i<10;i++) if (n%p[i]==0) return 0; for (ri i=0;i<10;i++) if (pow(p[i],n-1,n)!=1) return 0; LL f=n-1; while (1) if (f&1) break; f>>=1; LL t=pow(p[i],f,n); if (t!=1 && t!=n-1) return 0; if (t==n-1) break; return 1; LL solve(LL n) LL ret=1; while (!prime(n)) c=rand()%n; LL a=rand()%n,b=f(a,n); while (a!=b) LL cur=gcd(n,ads(b-a)); if (cur>1) n/=cur; ret=max(ret,solve(cur)); break; a=f(a,n); b=f(f(b,n),n); ret=max(ret,n); return ret; int main() int T; scanf("%d",&T); while (T--) ri i; scanf("%lld",&n); for (i=0;i<350;i++) if (n==q[i]) printf("%lld\n",ans[i]); break; if (n==q[i]) continue; if (prime(n)) puts("Prime"); continue; printf("%lld\n",solve(n)); return 0;
以上是关于P4718Pollard-Rho算法的主要内容,如果未能解决你的问题,请参考以下文章
@总结 - 10@ Miller-Rabin素性测试与Pollard-Rho因数分解
大数质因解:浅谈Miller-Rabin和Pollard-Rho算法