poj 3421 --X-factor Chains(数学、组合)

 

http://poj.org/problem?id=3421

 

X-factor Chains

Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 4495 Accepted: 1379

Description

Given a positive integer X, an X-factor chain of length m is a sequence of integers,

1 = X0, X1, X2, …, Xm = X

satisfying

Xi < Xi+1 and Xi | Xi+1 where a | b means a perfectly divides into b.

Now we are interested in the maximum length of X-factor chains and the number of chains of such length.

Input

The input consists of several test cases. Each contains a positive integer X (X ≤ 220).

Output

For each test case, output the maximum length and the number of such X-factors chains.

Sample Input

2
3
4
10
100

Sample Output

1 1
1 1
2 1
2 2
4 6

Source

 
 
 
解法:
s=p1^a1*p2^a2*p3^a3.....pn^an, 其中p1..pn为素数
因为素数不可再分,所以最大值为  (a1+a2+...+an)的最大值。
所以就看s能分解成几个素数的k次方。
所求得的数利用排列组合算下组合数即为最大长度的数量
组合数为 :(a1+a2...an)!/(a1!*a2!...*an!)
 
 
 
/*************************************************
*	核心原理:
*	s=p1^a1*p2^a2*p3^a3.....pn^an, 其中p1..pn为素数
**************************************************/
#include<cstdio>
#include<cstring>
#include <cmath>
const int M=(1<<20)+5;
bool is[M];
int prim[M>>1];
int a[100],k;
int getprm(int n)
{
	int i, j, k = 0;
	int s, e = (int)(sqrt(0.0 + n) + 1);
	memset(is, 1, sizeof(is));
	prim[k++] = 2; is[0] = is[1] = 0;
	for (i = 4; i < n; i += 2) is[i] = 0;
	for (i = 3; i < e; i += 2) if (is[i]) {
		prim[k++] = i;
		for (s = i * 2, j = i * i; j < n; j += s)
			is[j] = 0;
		// 因为j是奇数,所以+奇数i后是偶数,不必处理!
	}
	for ( ; i < n; i += 2) if (is[i]) prim[k++] = i;
	return k; // 返回素数的个数
}
int main()
{
	int i,t,k,sum1,j,n;
	__int64 sum2;
	t=getprm(M);
	while(scanf("%d",&n)==1)
	{
		if(is[n])
		{
			printf("1 1\n");
			continue;
		}
		k=0;
		for(i=0;i<t;i++)
		{
			if (n==1) 
				break;
			if (n%prim[i]==0)
			{
				a[k]=0;
				while(n%prim[i]==0) 
					n/=prim[i],a[k]++;	//p[k]=count(ak)
				k++;
			}
		}
		sum1=0;
		for(i=0;i<k;i++)		//sum1 = a1+a2..+an
			sum1+=a[i];
		sum2=1;
		for(i=1;i<=sum1;i++) 
			sum2*=i;
		for(i=0;i<k;i++)		//sum2 = (a1+a2...an)!/(a1!*a2!...*an!) 
			for(j=2;j<=a[i];j++)
				sum2/=j;
			printf("%d %I64d\n",sum1,sum2);
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值