訓練筆記

錯排問題

N個有序元素打亂,不在原來的位置上,求方案總數。
將n號球放入k號箱子,則第k號球可放入n號箱子(+Dn-2),也可以不放入n號箱子(+Dn-1).
k可取(n-1)次
Dn = (n-1)(Dn-2+Dn-1)

一道規律題

問題 B: cb的小心心卡牌
時間限制: 1 Sec 內存限制: 128 MB

題目描述

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];
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章