这怕是我写过最水的博客了
题意
有 n n n张桌子,每张桌子足够大能放下任意东西,现在有 3 3 3个红旗子, 5 5 5个蓝旗子,问放旗子的方案数。
解法
第一种方法是采用暴力,设
d
p
[
i
]
[
a
]
[
b
]
dp[i][a][b]
dp[i][a][b]表示放到第
i
i
i张桌子,已经放下
a
a
a个红旗子和
b
b
b个蓝旗子的方案数。输出
d
p
[
n
]
[
3
]
[
5
]
dp[n][3][5]
dp[n][3][5]即可。
第二种方法是直接数学计算。
5
5
5个蓝旗子的分配方案为
[
1
,
1
,
1
,
1
,
1
]
,
[
2
,
1
,
1
,
1
]
,
[
2
,
2
,
1
]
,
[
3
,
1
,
1
]
,
[
4
,
1
]
,
[
3
,
2
]
,
[
5
]
[1,1,1,1,1],[2,1,1,1],[2,2,1],[3,1,1],[4,1],[3,2],[5]
[1,1,1,1,1],[2,1,1,1],[2,2,1],[3,1,1],[4,1],[3,2],[5]。
其对应方案数为:
C
n
4
,
C
4
1
∗
C
n
4
(
插
空
法
)
,
C
3
1
∗
C
n
3
,
C
3
1
∗
C
n
3
,
C
2
1
∗
C
n
2
,
C
2
1
∗
C
n
2
,
C
n
1
C^{4}_{n},C^{1}_{4}*C^{4}_{n}(插空法),C^{1}_{3}*C^{3}_{n},C^{1}_{3}*C^{3}_{n},C^{1}_{2}*C^{2}_{n},C^{1}_{2}*C^{2}_{n},C^{1}_{n}
Cn4,C41∗Cn4(插空法),C31∗Cn3,C31∗Cn3,C21∗Cn2,C21∗Cn2,Cn1
3
3
3个红旗子的分配方案为
[
1
,
1
,
1
]
,
[
2
,
1
]
,
[
3
]
[1,1,1],[2,1],[3]
[1,1,1],[2,1],[3]。
其对应方案数为:
C
n
3
,
C
2
1
∗
C
n
2
,
C
n
1
C^{3}_{n},C^{1}_{2}*C^{2}_{n},C^{1}_{n}
Cn3,C21∗Cn2,Cn1
答案就是两个方案数的和相乘。
同时,我们可以归纳出
k
k
k个物品放在
n
n
n个桌子上的方案数为:
∑
i
=
1
k
C
k
i
∗
C
n
k
−
i
+
1
\sum^{k}_{i=1}C^{i}_{k}*C^{k-i+1}_{n}
∑i=1kCki∗Cnk−i+1
实现
这里仅提供方法一的实现。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<vector>
#include<cstring>
#include<map>
using namespace std;
#define LL long long
#define MAXN 500
int n;
LL dp[MAXN+5][6][4];
int main()
{
scanf("%d",&n);
dp[0][0][0]=1;
for(int i=1;i<=n;i++)
for(int j=0;j<=5;j++)
for(int k=0;k<=3;k++)
for(int p1=0;p1<=j;p1++)
for(int p2=0;p2<=k;p2++)
dp[i][j][k]+=dp[i-1][j-p1][k-p2];
printf("%lld",dp[n][5][3]);
}