概括一下题意:将一个合数n的因数(不包括1和n)看做一个集合,求一个最大的子集使集合内所有元素都互质,并求出在上述条件下集合元素最大的和是多少。
解法:既然要保证子集内的元素互质,就要保证任意两个元素没有质因子。要元素数目做多,则每个元素包含的质因子数目最少,即为1。
做法也就出来了,对n进行拆分质因数,表示成 n=(a1^p1)*(a2^p2)*(a3^p3)*......*(ak^pk),则子集大小就是k,子集所有元素的最大的和就是(a1^p1)+(a2^p2)+(a3^p3)+......+(ak^pk)。当然,有一种特殊情况,就是n只有一种质因数,n=a^p,例如16,9等等,因为n不在大的集合之内,所以sum=a^(p-1)
现在转化为了大数快速分解质因数的问题,可以使用神奇的“pollard-rho”算法
传送门:http://www.cnblogs.com/jackiesteed/articles/2019910.html
在pollard-rho算法中用到了Miller-Rabin素数检验
传送门:http://www.matrix67.com/blog/archives/234
如果感觉自己很难理解,还是老老实实套模板吧:
(kuangbin模板)
#include <ctime>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
/*
Miller_Rabin 算法判断是否为素数
*/
const int S=8;
//ret=(a*b)%c;
LL mult_mod(LL a,LL b,LL c)
{
a %= c;
b %= c;
LL ret=0;
LL tmp=a;
while(b)
{
if(b&1)
{
ret+=tmp;
if(ret>c) ret-=c;
}
tmp<<=1;
if(tmp>c) tmp-=c;
b>>=1;
}
return ret;
}
//res=x^n %mod;
LL pow_mod(LL x,LL n,LL mod)
{
LL t,res;
res=1;
t=x;
while(n)
{
if(n&1)
res=mult_mod(res,t,mod);
n>>=1;
t=mult_mod(t,t,mod);
}
return res;
}
//是合数返回1,不一定是合数返回0
bool check(LL a, LL n, LL x, LL t)
{
int i;
LL ret=pow_mod(a,x,n);
LL last=ret;
for(i=1;i<=t;i++)
{
ret=mult_mod(ret,ret,n);
if(ret==1 && last!=1 && last!=n-1) return 1;
last=ret;
}
if(ret!=1)
return 1;
else
return 0;
}
//很可能是素数返回1,一定不是素数返回0
bool Miller_Rabin(LL n)
{
int i;
if (n<2) return 0;
if (n==2) return 1;
if ((n&1)==0) return 0;
LL x=n-1;
LL t=0;
while((x&1)==0)
{
x>>=1;
t++;
}
srand(time(NULL));
for(i=0;i<S;i++)
{
LL a=rand()%(n-1)+1;
if(check(a,n,x,t))
return 0;
}
return 1;
}
/*
pollard_rho算法进行质因数分解
*/
LL factor[1000];
int tol;//质因数个数
LL gcd(LL a,LL b)
{
LL t;
while(b)
{
t=a;
a=b;
b=t%b;
}
if(a>=0) return a;
else return -a;
}
LL pollard_rho(LL x,LL c)
{
LL i=1,k=2;
srand(time(NULL));
LL x0=rand()%(x-1)+1;
LL y=x0;
while(1)
{
i++;
x0=(mult_mod(x0,x0,x)+c)%x;
LL d=gcd(y-x0,x);
if(d!=1 && d!=x) return d;
if(y==x0) return x;
if(i==k)
{
y=x0;
k+=k;
}
}
}
void findfac(LL n,int k)
{
if(n==1) return ;
if(Miller_Rabin(n))
{
factor[tol++]=n;
return ;
}
LL p=n;
int c=k;
while(p>=n)
p=pollard_rho(p,c--);
findfac(p,k);
findfac(n/p,k);
}
void work()
{
int i;
LL n,ans,tmp,cnt;
scanf("%I64d",&n);
tol=0;
findfac(n,107);
sort(factor,factor+tol);
ans=0;
tmp=factor[0];
cnt=1;
for(i=1;i<tol;i++)
{
if(factor[i]!=factor[i-1])
{
cnt++;
ans+=tmp;
tmp=factor[i];
}
else
{
tmp*=factor[i];
}
}
ans+=tmp;
if(cnt==1) ans/=factor[0];
printf("%I64d %I64d\n",cnt,ans);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
work();
return 0;
}