Description
红蓝球各无限多个.
初始时随意地从中选择 n 个, 扔入箱子
初始有一个空的序列
接下来依次做 m 组操作, 每组操作为依次执行下述三个步骤
(1) 从箱子中取出一个求插入序列尾
(2) 往箱子里补充 一红一蓝
(3) 从箱子中取出一个求插入序列尾
求 mm 次操作后, 有多少种不同的颜色序列, 答案对 109+7 取模
Input
第一行两个数 n,mn,m .
Output
一个数 ans 表示答案对 10^9+7 取模的值.
Sample Input
# 样例输入1
2 3
# 样例输入2
1000 10
# 样例输入3
1000 3000
Sample Output
# 样例输出1
56
# 样例输出2
1048576
# 样例输出3
693347555
HINT
样例解释1
一共有 6 个球会被从盒子中取出.
一个方案是不合法的当且仅当第 2,3,4,5 个球的颜色完全相同.
所以答案为 26−23=56
数据范围
n,m≤3000
Sol
定义(f[i][j])为进行i轮,红球j个的方案数,然后跑普及组dp,但是这样会重复,原因:一个最终序列可能是由多个初始集合生成的。但是我们发现,如果开始有i个红球能够生成一个序列,i+j个也可以,那么我们找到这个最小的i,可以发现一定会用完,所以再加一维([0/1])表示有没有用完过红球,然后就不会有重复了。
Code
#include <cstdio>
int n,m,f[3005][3005][2],ans;const int P=1e9+7;
int main()
{
scanf("%d%d",&n,&m);f[0][0][1]=1;
for(int i=1;i<=n;i++) f[0][i][0]=1;
for(int i=0;i<m;i++) for(int j=0;j<=n;j++) for(int k=0;k<=1;k++)
{
if(j) f[i+1][j-1][k|!(j-1)]=(f[i+1][j-1][k|(j==1)]+f[i][j][k])%P;
if(n-j) f[i+1][j+1][k]=(f[i+1][j+1][k]+f[i][j][k])%P;
if(j) f[i+1][j][k|(j==1)]=(f[i+1][j][k|(j==1)]+f[i][j][k])%P;
if(n-j) f[i+1][j][k]=(f[i+1][j][k]+f[i][j][k])%P;
}
for(int i=0;i<=n;i++) ans=(ans+f[m][i][1])%P;
printf("%d
",ans);
}