这怕是我写过最水的博客了
题意
有nnn张桌子,每张桌子足够大能放下任意东西,现在有333个红旗子,555个蓝旗子,问放旗子的方案数。
解法
第一种方法是采用暴力,设dp[i][a][b]dp[i][a][b]dp[i][a][b]表示放到第iii张桌子,已经放下aaa个红旗子和bbb个蓝旗子的方案数。输出dp[n][3][5]dp[n][3][5]dp[n][3][5]即可。
第二种方法是直接数学计算。
555个蓝旗子的分配方案为[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]。
其对应方案数为:Cn4,C41?Cn4(插空法),C31?Cn3,C31?Cn3,C21?Cn2,C21?Cn2,Cn1C^{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?
333个红旗子的分配方案为[1,1,1],[2,1],[3][1,1,1],[2,1],[3][1,1,1],[2,1],[3]。
其对应方案数为:Cn3,C21?Cn2,Cn1C^{3}_{n},C^{1}_{2}*C^{2}_{n},C^{1}_{n}Cn3?,C21??Cn2?,Cn1?
答案就是两个方案数的和相乘。
同时,我们可以归纳出kkk个物品放在nnn个桌子上的方案数为:∑i=1kCki?Cnk?i+1\sum^{k}_{i=1}C^{i}_{k}*C^{k-i+1}_{n}∑i=1k?Cki??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]);
}