2012 Multi-University Training Contest 5:Mark the Rope

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.
 
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<263) 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;
}		


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章