DP解Stringsobits

Stringsobits
Kim Schrijvers

Consider an ordered set S of strings of N (1 <= N <= 31)bits. Bits, of course, are either 0 or 1.

This set of strings is interesting because it is ordered andcontains all possible strings of length N that have L (1 <= L<= N) or fewer bits that are `1'.

Your task is to read a number I (1 <= I <= sizeof(S))from the input and print the Ith element of the ordered set for Nbits with no more than L bits that are `1'.

PROGRAM NAME: kimbits

INPUT FORMAT

A single line with three space separated integers: N, L, and I.

SAMPLE INPUT (file kimbits.in)

5 3 19

OUTPUT FORMAT

A single line containing the integer that represents the Ith elementfrom the order set, as described.

SAMPLE OUTPUT (file kimbits.out)

10011


分析

分3步进行

1.c[i][j]为位数为i,含有1的个数为j的二进制数的个数。其实c[i][j]就是组合数,这个数组就是杨辉三角。初始化后迭代求解这个数组。

2.c[i][j]现在为位数为i,含有1的个数小于等于j的二进制数的个数。叠加。

3.求解第I小的二进制数:从高到低依次求出每一位

总结:题目中的“第I大”应该是第I小,另外注意I值用int越界问题,用unsigned int即可。


通过代码

/*
ID: c1033311
LANG: C++
TASK: kimbits
*/
#include<stdio.h>

int main(){
	FILE *fin=fopen("kimbits.in","r");
	FILE *fout=fopen("kimbits.out","w");

	unsigned int N,L,I;
	unsigned int c[32][32]; //c[i][j]为位数为i,含有1的个数为j的二进制数的个数
	unsigned int i,j;

	fscanf(fin,"%u%u%u",&N,&L,&I);

	//初始化c[i][j]
	for(i=0;i<=N;++i)
	{
		c[i][0]=1;  //全0
		c[i][i]=1;	//全1
	}


	//迭代求解c[i][j]
	for(i=2;i<=N;++i)
		for(j=1;j<=L&&j<i;++j)
			c[i][j]=c[i-1][j]+c[i-1][j-1];


	//c[i][j]现在为位数为i,含有1的个数小于等于j的二进制数的个数
	for(i=1;i<=N;++i)
		for(j=1;j<=L&&j<=i;++j)
			c[i][j]+=c[i][j-1];



	//求解第I小的二进制数:从高到低依次求出每一位

	unsigned int sum=0; //目前为止满足要求的二进制数个数
	unsigned int n1=0; //目前为止用掉1的个数

	for(i=1;i<=N;++i)
	{
		unsigned int tmp=L-n1;
		if(tmp>N-i)
			tmp=N-i;

		if(c[N-i][tmp]+sum==I-1)
		{
			fprintf(fout,"1");
			for(j=i+1;j<=N;++j)
				fprintf(fout,"0");
			break;
		}
		else if(c[N-i][tmp]+sum<I-1)
		{
			fprintf(fout,"1");
			sum+=c[N-i][tmp];
			n1++;
		}
		else
			fprintf(fout,"0");
	}

	fprintf(fout,"\n");

	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值