题解
%%% 神犇!!!
这里介绍一种奇妙的做法,不难理解,代码也很好写。
其实并不需要考虑每种情况下
具体是多少,只需要根据当前情况需要再决定,可以证明以下情况都是存在
使之成立的:
这里设
,初始有
个红球,
个蓝球可以把取球分成三个部分的动作:
- 位置未变空
- 位置变空, 位置未变空
- 均变空,此时只能从 位置取球
显然第
部分取球的序列是由前
部分决定且唯一的,所以不再考虑。
蓝球全部连续出现的情况太过特殊,在这里单独列出连续出现的情况数为
。接下来讨论到的情况都是蓝球存在间隔出现的情况:
进一步把
过程细分:
1.1. 取出一些红球
1.2. 取出第一个蓝球,取出总共
个球,其中含有
个蓝球。
2.1. 取出一些红球
2.2. 取出第一个蓝球,取出总共
个球,其中含有
个蓝球。
这样便枚举到了所有可能的情况,想象即使可能
的取值并不支持在1.2.取出
个球,但之后的操作也会出现同样的效果,把
前移是等效的。
这个不好证明,感性理解,我认真想了还是不会啊TAT。
所以统计答案只需要枚举
,再利用组合计数计算出当前
下的方案数:
首先需要满足
,方案数:
这里用到隔板法,
指把
个球放进
个箱子,每个箱子至少放一个的方案数,这里具体指1.2.中有
个蓝球,把
个球任意放进
个蓝球之后的方案。同理可得,
表示2.2.的情况。
则表示除掉1.2. 2.2.两次放入的红球外,剩余的红球分别在1.1. 2.1. 3.任意个数(某次可以为空)全部放入的方案数。
组合数预处理一下即可。
代码
#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7,N=2050;
int a,b,c[N][N],ans;
inline int ad(int x,int y){x+=y;if(x>=mod) x-=mod;return x;}
inline int mul(int x,int y){return 1ll*x*y%mod;}
int main(){
int i,j;
c[0][0]=1;
for(i=1;i<N;++i){
c[i][0]=c[i][i]=1;
for(j=1;j<i;++j) c[i][j]=ad(c[i-1][j-1],c[i-1][j]);
}
scanf("%d%d",&a,&b);
ans=a+1;
for(i=max(1,b-a);i<b;++i)
for(j=max(1,2*(b-i)-a);j<=b-i;++j)
ans=ad(ans,mul(mul(c[b-1][i-1],c[b-i-1][j-1]),c[a-2*(b-i)+j+2][2]));
printf("%d\n",ans);
}