HDU 2062 Subset sequence (数学)

一道数学题,很有趣,看了很多题解才懂。

首先是要求出An数组的子集和有多少个。

数学拙鸡就不写推导过程了,有兴趣可以自己去搜。

A[n]=(A[n-1])*(n-1)+1;

引用一段解释的很好的过程解释来说下3 10 这组数据是怎么处理的(语文拙计)

因为n=3,所以开始数组里1、2、3三个数。
我们知道,n=2时,有4种排列,所以上面n=3可以分成三组,每组5个(加上空集)。
因此第10个在第二组里。所以第一个是2,把2输出。原来的数组里删除2,变成1、3两个数。然后10 - (2 - 1) * 5 = 5,即它在第2组的第5个。
减去首个空集合,5 - 1 = 4 ≠ 0,表示2后面还有数字。
因为A1 = 1是,所以再第2组里又可以分成两组,每组2个(加上空集)。
所以,4在第2组,剩下的数组中,第二个元素是3,所以输出3。再把数组里的3删除,剩下1一个数。
然后4 - (2 - 1) * 2 = 2,既它是第2组的第2个。
减去首个空集,2 - 1 = 1 ≠ 0,表示2后面还有数字。
按上面的方法继续下去,直到n = 0 或 后面为空集为止。
最后输出数组里的第1个元素,就得到2 3 1,就是解了。

 

#include <stdio.h>
#include <algorithm>
#include <math.h>
#include <string.h>
using namespace std; 
int main(int argc, char *argv[])
{
	int t;
	int i,j;
	int n,s[30];;
	long long int m,c[25]={0};
	for(i=0;i<21;i++)
	{
		c[i]=c[i-1]*(i-1)+1;
		//printf("%lld\n",c[i]);
	}//求出每个数字分组里的个数 
	while(scanf("%d %lld",&n,&m)!=EOF)
	{
		for(i=0;i<26;i++)
			s[i]=i;//初始赋值 
		while(n>0&&m>0) 
		{
			t=m/c[n]+1;//判断第m个数在那一组 
			//printf("*****m=%lld cn=%lld t=%d\n",m,c[n],t);
			if(m%c[n]==0)
				t--;
			if(t>0)
			{
				printf("%d",s[t]);//先输出t组的首数字 
			//	printf("*******%d\n",t);
				for(i=t;i<=n;i++)
				{
					s[i]=s[i+1];//在第n组中,第2个元素在第n个时变为它的下一个数 
				}		
				m=m-((t-1)*c[n]+1);//m变为表示在剩余子集中位于第几个 
			//	printf("*******%d\n",m);						
				if(m==0)
					printf("\n");		
				else
					printf(" ");	
			}
			n--;
		}
	}
	return 0;
}
//Start-ZJ
//2017/12/14/10:01

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值