HDU4602 Partition (神奇的計算方式)

題目描述:

4=1+1+1+1   =1+1+2   =1+2+1   =2+1+1   =1+3   =3+1   =44=1+1+1+1\\~~~=1+1+2\\~~~=1+2+1\\~~~=2+1+1\\~~~=1+3\\~~~=3+1\\~~~=4
上述對正整數4的拆分中1出現了12次,現給出n,k109n,k\le10^9,求對n的拆分中數字k出現的次數
多組數據,T<=10000

題目分析:

首先,對一個數n的所有拆分方案總共有2n12^{n-1}種,相當於在n相同的小球中插入p塊隔板(p=0,1,2…n-1),那麼總方案數爲Cn10+Cn11++Cn1n1=(1+1)n1=2n1C_{n-1}^0+C_{n-1}^1+\cdots +C_{n-1}^{n-1}=(1+1)^{n-1}=2^{n-1}
由於k在同一個拆分中可能出現多次,不好處理,我們先考慮只計算一次的情況

  • n<k 輸出0

  • n=k 輸出1

  • n=k+1 輸出2

  • n>k+1
    這時k倘若在靠左邊的位置,則右邊的數隨意拆分,數量爲2nk12^{n-k-1},k靠右同理
    倘若k在中間,則有n-k-1個位置可選,設兩邊的數爲t1,t2,則拆分方案數爲2t112t21=2nk22^{t1-1}*2^{t2-1}=2^{n-k-2}
    總的加起來就是2nk+(nk1)2nk2=(nk+3)2nk22^{n-k}+(n-k-1)*2^{n-k-2}=(n-k+3)*2^{n-k-2}

    但是,此時我們只求出了一個k的情況,同一種拆分中k出現多次怎麼辦?
    其實思考一下,問題已經無意中解決了,若同一種拆分中有p個k,那麼這種拆分就會被統計到p次,因爲我們並沒有管除了當前的k之外其他地方還會不會出現k,舉個例子:
    8=1+8=1+ 2\color{red}2 ++ 2\color{green}2 ++ 2\color{blue}2 +1+1 這種拆分中,在2\color{red}22\color{green}22\color{blue}2時各統計了一次,係數問題已經解決了

總結一下,有些時候統計問題的去重操作其實很簡單,對稱的感覺很重要
比如這道題,看似會算重的統計方式實際上把次數也求出來了。

PS:要是在考場上,直接列表格:
n,k1234511221352141252152812521\begin{array}{c|ccccc} n,k&amp;1&amp;2&amp;3&amp;4&amp;5\\\hline 1&amp;1\\ 2&amp;2&amp;1\\ 3&amp;5&amp;2&amp;1\\ 4&amp;12&amp;5&amp;2&amp;1\\ 5&amp;28&amp;12&amp;5&amp;2&amp;1 \end{array}
很容易發現只跟n-k的大小有關

#include<cstdio>
const int mod = 1e9+7;
int ksm(int a,int b)
{
	int s=1;
	for(;b;b>>=1,a=1ll*a*a%mod) if(b&1) s=1ll*s*a%mod;
	return s;
}
int main()
{
	int T,n,k;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&n,&k);
		if(n<k) puts("0");
		else if(n<=k+1) printf("%d\n",n-k+1);
			else printf("%d\n",1ll*(n-k+3)*ksm(2,n-k-2)%mod);
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章