Eric has a long rope whose length is N, now he wants to mark on the rope with different colors. The way he marks the rope is:
1. He will choose a color that hasn’t been used
2. He will choose a length L (N>L>1) and he defines the mark’s value equals L
3. From the head of the rope, after every L length, he marks on the rope (you can assume the mark’s length is 0 )
4. When he chooses the length L in step 2, he has made sure that if he marks with this length, the last mark will be at the tail of the rope
Eric is a curious boy, he want to choose K kinds of marks. Every two of the marks’ value are coprime(gcd(l1,l2)=1). Now Eric wants to know the max K. After he chooses the max K kinds of marks, he wants to know the max sum of these K kinds of marks’ values.
You can assume that Eric always can find at least one kind of length to mark on the rope.
3 18
3 22
//题目其实要求的是选取n的一些因子(不包括1和它本身)存放在一个集合里,使得这个集合里的数两两之间互质(1),且所有数之和最大(2)! 最后输出满足题意的集合里元素的个数已经所有元素之和。
//要使得选取出来的因子组成的集合满足第(1)个条件,那么这些因子之间必定没有公因子,集合里面的元素本身质因子分解后只有一个质因子。那么集合元素的个数其实就是n质因子分解后质因子的个数。 而要满足条件(2),则需要再满足条件(1)的基础上,每个元素越大越好,而本身又只能由一个质因子,所以需要在对n质因子分解时将所有相同质因子相乘作为集合的一个元素。这样得到的才是最佳集合! 需要注意的是当n本身只有一个质因子的时候即n=p^k,因为 要求n>L>1,所以集合里面只有一个元素,并且为p^(k-1)。
//n的范围是long long则需要用到Pollard素数分解。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<algorithm>
#include<ctime>
using namespace std;
#define LL __int64
#define MAX (pow(2.0,62))
#define C 240
#define TIME 15
LL a[105];
int cnt=0;
LL gcd(LL a,LL b)
{
if(b==0)
return a;
return gcd(b,a%b);
}
LL mod_mult(LL a,LL b,LL n)
{
LL s=0;
a=a%n;
while(b)
{
if(b&1)
{
s+=a;
if(s>=n) s-=n;
}
a<<=1;
if(a>=n) a-=n;
b>>=1;
}
return s;
}
LL mod_exp(LL a,LL b,LL n)
{
LL d=1;
a=a%n;
while(b>=1)
{
if(b&1)
d=mod_mult(d,a,n);
a=mod_mult(a,a,n);
b=b>>1;
}
return d;
}
bool Wintess(LL a,LL n)
{
__int64 m,x,y;
int i,j=0;
m=n-1;
while(m%2==0)
{
m=m>>1;
j++;
}
x=mod_exp(a,m,n);
for(i=1;i<=j;i++)
{
y=mod_exp(x,2,n);
if(y==1&&x!=1&&(x!=(n-1)))
return true;
x=y;
}
if(y!=1)
return true;
return false;
}
bool miller_rabin(int times,LL n)
{
__int64 a;
int i;
if(n==1)
return false;
if(n==2)
return true;
if(n%2==0)
return false;
srand(time(NULL));
for(i=1;i<=times;i++)
{
a=rand()%(n-1)+1;
if(Wintess(a,n))
return false;
}
return true;
}
LL Pollard(LL n,int c)
{
LL i,k,x,y,d;
srand(time(NULL));
i=1; k=2;
x=rand()%n;
y=x;
while(true)
{
i++;
x=(mod_mult(x,x,n)+c)%n;
d=gcd(y-x,n);
if(d>1&&d<n)
return d;
if(y==x)
return n;
if(i==k)
{
y=x;
k=k<<1;
}
}
}
void get_prime(LL n,int c)
{
LL m;
if(n==1)
return;
if(miller_rabin(TIME,n))
{
a[++cnt]=n;
return;
}
m=n;
while(m==n)
m=Pollard(n,c--);
get_prime(m,c);
get_prime(n/m,c);
}
int main()
{
int t;
LL n;
scanf("%d",&t);
while(t--)
{
cnt=0;
scanf("%I64d",&n);
get_prime(n,C);
sort(a+1,a+cnt+1);
int num=1,i;
LL sum=0,tmp=1;
for(i=1;i<cnt;i++)
{
tmp*=a[i];
if(a[i]!=a[i+1])
sum+=tmp,num++,tmp=1; //相同的质因子归类
}
sum+=tmp*a[i];
if(num>1)
printf("%d %I64d\n",num,sum);
else
printf("1 %I64d\n",tmp);
}
return 0;
}