1. 程式人生 > >Wannafly 挑戰賽16 A 取石子

Wannafly 挑戰賽16 A 取石子

def 表示 ++i 備註 spl one str 打表 sub

題目描述 給出四堆石子,石子數分別為a,b,c,d。規定每次只能從堆頂取走石子,問取走所有石子的方案數。

輸入描述:

在一行內讀入四個由空格分隔的整數a,b,c,d, 輸入均為不超過500的正整數

輸出描述:

輸出一個整數表示答案,答案對109+7取模
示例1 輸入
3 5 4 2
輸出
2522520

備註:

輸入均為不超過500的正整數

【分析】

每一堆的石子之間的相對位置是固定不變的,所以可以通過插入來生成一個取石子的順序,而插入的求解則可以利用組合數來計算。 起始的時候,把第一堆的$$$a$$$個石頭擺好,相當於在$$$a$$$個空位放下$$$a$$$個石頭,由於石頭順序是固定的,所以有$$$C^a_a$$$種,也就是1種;

技術分享圖片

接下來,把第二堆的$$$b$$$個石頭也加進來,要在$$$a$$$個石頭之間以及兩邊插入$$$b$$$個石頭,等價於一共有$$$a+b$$$個位置,在其中選$$$b$$$個位置,作為放置$$$b$$$的地方,由於$$$b$$$的順序確定,所以組合數為$$$C^b_{a+b}$$$個

技術分享圖片

然後把第三堆的$$$c$$$個石頭也加進來,在$$$a+b$$$個石頭插入$$$c$$$個石頭,同理,組合數為$$$C^c_{a+b+c}$$$個;

技術分享圖片

第四堆的$$$d$$$加進來就是$$$C^d_{a+b+c+d}$$$個。 所以最終答案為$$$C^a_a \times C^b_{a+b} \times C^c_{a+b+c} \times C^d_{a+b+c+d}$$$個


【註意】

組合數較大需要用long long存放;對答案需要取模 可以對組合數打表,來避免分數取模,公式為$$$C^x_y = C^x_{y-1} + C^{x-1}_{y-1}$$$

技術分享圖片


【代碼】

#include<stdio.h>
#define N_max 2005
int n;
typedef long long ll;
#define mod 1000000007

ll C[N_max][N_max] = { 0 };

int main() {

int a[4];
	ll res = 1;
	for (int t = 0; t < N_max; ++t)C[t][0]=1;

	for (int i = 1; i <N_max; ++i)
		for (int j = 1; j <=i; ++j) {
			C[i][j] = (C[i - 1][j - 1] + C[i - 1][j])%mod;
		}
	for (int i = 0; i < 4; ++i)
	{
		scanf("%d", a + i);
	}
	res = C[a[0]][a[0]];
	res = res*C[a[0] + a[1]][a[1]]%mod;
	res = res*C[a[0] + a[1]+a[2]][a[2]]%mod;
	res = res*C[a[0] + a[1]+a[2]+a[3]][a[3]]%mod;

	printf("%lld", res);
	return 0;
}

Wannafly 挑戰賽16 A 取石子