cb的小心心卡牌

一道规律题

题目描述

cb是一个非常优秀的学长,他拥有一套自己心仪的卡牌,他将其命名为“小心心”卡牌。
cb的卡牌很独特,卡牌的面值都是2的次幂,比如1、2、4、8、16…等,你可以认为每个2的次幂的面值cb都有,并且每个面值的卡牌都只有2张。
现在cb得到了一项任务,他被要求用“小心心”卡牌来拼凑出总面值为n的卡牌集合。cb想知道他有多少种方法可以得到总面值为n。

输入
第一行一个整数T (0<T<1000)
接下来每行一个数字n (0<n<1000000)

输出
输出T行,每行为凑出n的方法总数

样例输入
2
1
2

样例输出
1
2
提示
第一个样例1只有一种拼凑方法,即 1
第二个样例2有两种拼凑方法,即2 与 1,1

Solution:用2的次幂凑数,也就是用二进制表示数。每两个低次幂的数的和即为高进制数:1+1=2,2+2=4,4+4=8。如果数字为16,即10000,则组合的方式为16,8+8,8+4+4,8+4+2+2,8+4+2+1+1,这五种写法;同时推到其他数字,如果1010,即10这个数字,二进制表示方法为8+2,所以我们将8与2的组合方式求出即可,注意处理8与2表示方法重合的部分,即如果8表示为4+2+2,则2只能为1+1。

//std
#include<stdio.h>
#include<algorithm>
using namespace std;
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int n;
		scanf("%d",&n);
		int sum=0;//用sum来处理方案重叠的方法,并且sum记录的是不含当前位置为1的方案数的总和
		int Max=1;//Max记录为已经处理过的以1开头的方案数
		while(n)
		{
		   if(n%2==0)
			   sum+=Max; 
		   else
			   Max+=sum;
		   n/=2;
		}
		printf("%d\n",Max);
	}
	return 0;
}

dp做法:

	dp[1]=1;
    dp[2]=2;
    for (int j=3;j<=1000000;j++)
    {
     if (j%2!=0)//j为奇数
        dp[j]=dp[j-1]-dp[j-2];
     else//j为偶数
        dp[j]=dp[j-1]+dp[j/2];
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值