#Pollard-Rho,高精度#洛谷 3499 [POI2010]NAJ-Divine Divisor

题目

给定\(m\)个数\(a_i\),令\(n=\prod_{i=1}^m a_i\)
问有多少个大于1的正整数\(d\)满足\(d^{\max k}|n\)
并输出\(\max k\)\(m\leq 600,a_i\leq 10^{18}\)


分析

\(a_i\)质因数分解,\(n\)的指数累加,那么就可以使\(n\)质因数分解,
若有\(p\)个质数使得\(p^{\max k}|n\)\(d\)的个数为\(2^p-1\)
由于\(p\leq 600\),所以要高精度乘法


代码

#include <cstdio>
#include <cctype>
#include <cmath>
#include <cstdlib>
#include <map>
#define rr register
using namespace std;
const double ha=pow(11.0,19/17.0);
const int prime[8]={2,61,97,7,13,17,23,29},MOD=1000000000;
typedef long long lll; lll x,n,tot,mx,ans,p[41],dig[211];
map<lll,int>uk; map<lll,int>::iterator it;
inline lll iut(){
	rr lll ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans; 
}
inline lll mo(lll a,lll b,lll mod){return a+b>=mod?a+b-mod:a+b;}
inline lll mul(lll a,lll b,lll mod){return (a*b-(lll)((long double)a/mod*b)*mod+mod)%mod;}
inline lll gcd(lll a,lll b){return b?gcd(b,a%b):a;}
inline lll ksm(lll x,lll y,lll mod){
	rr lll ans=1;
	for (;y;y>>=1,x=mul(x,x,mod))
	    if (y&1) ans=mul(ans,x,mod);
	return ans;
}
inline bool mr(lll n){
	if (n==1) return 0;
	for (rr int i=0;i<8;++i)
	    if (n==prime[i]) return 1;
	for (rr int i=0;i<8;++i)
	    if (n%prime[i]==0) return 0;
    rr lll m=n-1; rr int cnt=0;
    while (!(m&1)) m>>=1,++cnt;
	for (rr int i=0;i<8&&prime[i]<n;++i){
		rr lll now=ksm(prime[i],m,n),ls=now;
		for (rr int j=1;j<=cnt;++j){
			now=mul(now,now,n);
			if (now==1&&ls!=1&&ls!=n-1) return 0;
			ls=now;
		}
		if (now!=1) return 0;
	} 
	return 1;
}
inline lll rho(lll n,lll h){
	if (!(n&1)) return 2;
	if (!(n%3)) return 3;
	rr lll x1=(rand()+1)%n,x2=x1,p=1;
	for (rr int k=2;;k<<=1,x2=x1,p=1){
		for (rr int i=1;i<=k;++i){
			x1=mo(mul(x1,x1,n),h,n);
			p=mul(p,x1>x2?x1-x2:x2-x1,n);
			if (!(i&127)){
				rr lll d=gcd(p,n);
				if (d>1) return d;
			}
		}
		rr lll d=gcd(p,n);
		if (d>1) return d;
	}
}
inline void dfs(lll n){
	if (n==1) return;
	if (mr(n)){
		p[++tot]=n;
		return;
	}
	rr lll t=n;
	while (t==n) t=rho(n,rand()%(n-1)+1);
	while (!(n%t)) n/=t;
	dfs(t),dfs(n);
}
inline void cheng(int t){
	rr lll s=0,g=0;
	for (rr int i=1;i<=dig[0];++i)
	    s=dig[i]*t+g,g=s/MOD,dig[i]=s%MOD;
	if (g) dig[++dig[0]]=g;
}
signed main(){
	n=iut(),srand((unsigned)((lll)(new char)*ha));
	for (rr int i=1;i<=n;++i){
		tot=0,dfs(x=iut());
		for (rr int i=1;i<=tot;++i){
			rr int c=0;
			while (x%p[i]==0) x/=p[i],++c;
			uk[p[i]]+=c;
		}
	}
	for (it=uk.begin();it!=uk.end();++it)
	if (mx<it->second) mx=it->second,ans=1;
		else if (mx==it->second) ++ans;
	dig[dig[0]=1]=1;
	for (rr int i=1;i<=ans/25;++i) cheng(33554432);
	if (ans%25) cheng(1<<(ans%25));
	--dig[1],printf("%lld\n",mx);
	printf("%lld",dig[dig[0]]);
	for (rr int i=dig[0]-1;i;--i) printf("%09lld",dig[i]);
	return 0;
}
posted @ 2021-03-31 16:57  lemondinosaur  阅读(67)  评论(0编辑  收藏  举报