版权声明:未经过同意不得转载 https://blog.csdn.net/qq_42500298/article/details/83108068
题目描述
给定非负整数a,b,c,d,求有多少对01串(S,T),满足以下条件: - S 由 a 个 0 , b 个 1 组成 - T 由 c 个 0 , d 个 1 组成 - T 可以由 S 删掉一些字符得到 由于答案可能过大,你只需要输出答案对 1000000007 取模后的值
输入描述:
第一行四个非负整数 a , b , c , d对于 的数据,有a,b,c,d≤ 3对于 的数据,有a,b,c,d≤ 50对于 的数据,有a,b,c,d≤ 300另有 的数据,有 c=0对于 的数据,有0≤ a,b,c,d≤ 2000,且0≤ c≤ a,0≤ d≤ b,a+b≥ 1,c+d≥ 1
输出描述:
输出一个非负整数表示答案
示例1
输入
2 1 1 1
输出
4
说明
(001,01) , (010,10),(010,01) , (100,10)
思路
t 是从 s 中删除一些字符得到的,t 一共有 C(c+d,c) 种,考虑逆过程,我们 在 t 上面插入 a-c 个 0,b-d 个 1 来得到 s
可以枚举末尾有几个 0 几个 1,然后用插板法统计方案。
代码里还有一些要注意的地方
代码
include<bits/stdc++.h>
using namespace std;
const long long MOD=1e9+7;
const long long N=5005;
long long C[N][N];
long long calc(long long x,long long y)//x放入y个东西里面
{
if(x==0)
return 1;
if(y<=0)
return 0;
return C[x+y-1][y-1];
}
int main()
{
C[0][0]=1;
for(long long u=1;u<=5000;u++)
{
C[u][0]=1;
for(long long i=1;i<=u;i++)
C[u][i]=(C[u-1][i-1]+C[u-1][i])%MOD;
}
long long a,b,c,d;
scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
a=a-c;b=b-d;
long long ans=0;//枚举末尾有i个0,j个1
for(long long u=0;u<=a;u++)
{
for(long long i=0;i<=b;i++)//放在最后面有多少个
{
long long x=a-u,y=b-i;
ans=(ans+C[u+i][u]*calc(y,c)%MOD*calc(x,d)%MOD)%MOD;
}
}
ans=ans*C[c+d][d]%MOD;
printf("%lld\n",ans);
return 0;
}
来源:nkw