Problem Description
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.
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.
Input
First line: a positive number T (T<=500) representing the number of test cases
2 to T+1 lines: every line has only a positive number N (N<2 63) representing the length of rope
2 to T+1 lines: every line has only a positive number N (N<2 63) representing the length of rope
Output
For every test case, you only need to output K and S separated with a space
SampleInput
2 180 198
SampleOutput
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; }