[SCOI2010]生成字符串

问题描述

给出 n , m ( n ≥ m ) n,m(n\ge m) n,m(nm),求长度为 n + m n+m n+m含有 n n n 1 1 1 m m m 0 0 0且其任意一个前缀满足前缀中 1 1 1的数量大于等于 0 0 0的数量的字符串的数量,对 20100403 20100403 20100403取模。

无约束条件的方案数为 C ( n + m , m ) C(n+m,m) C(n+m,m)
0 0 0改做 − 1 -1 1,那么题意转换为,字符串任意一个前缀的前缀和都 ≥ 0 \ge 0 0

充分性

考虑一个不满足约束条件的字符串,找到其第一个前缀和为 − 1 -1 1的位置,设其前面有 x x x 1 1 1 − 1 -1 1,则其后面有 n − x n-x nx 1 1 1 m − 1 − x m-1-x m1x − 1 -1 1,将这个位置后面的 1 1 1改为 − 1 -1 1 − 1 -1 1改为 1 1 1,那么总的 1 1 1的数量变为 x + m − 1 − x = m − 1 x+m-1-x=m-1 x+m1x=m1个,总的 − 1 -1 1的数量变为 x + 1 + ( n − x ) = n + 1 x+1+(n-x)=n+1 x+1+(nx)=n+1个,于是计算不满足约束条件的方案数为 C ( n + m , m − 1 ) C(n+m,m-1) C(n+m,m1)

必要性

f ( n , m ) f(n,m) f(n,m)表示含有 n n n 1 1 1 m m m − 1 -1 1的字符串。
f ( m + 1 , n − 1 ) f(m+1,n-1) f(m+1,n1)是否可以根据充分性唯一还原出一个不合法的 f ( n , m ) f(n,m) f(n,m),取决于其是否含有前缀和 − 1 -1 1
n ≥ m n\ge m nm ( m − 1 ) ∗ 1 + ( n + 1 ) ∗ − 1 ≥ − 2 (m-1)*1+(n+1)*-1\ge -2 (m1)1+(n+1)12,显然必含有前缀和为 − 1 -1 1的前缀。
又题设有约束 n ≥ m n\ge m nm,故结论成立。
注:当 n = m n=m n=m时, C ( 2 ∗ n , n ) − C ( 2 ∗ n , n − 1 ) C(2*n,n)-C(2*n,n-1) C(2n,n)C(2n,n1)为卡特兰数,本题实际为卡特兰数的一个推广。

#include<bits/stdc++.h>
using namespace std;
const int N=2e6+5,mod=20100403;
typedef long long ll;
ll f[N],invf[N];
ll C(ll n,ll m)
{
    return f[n]*invf[n-m]%mod*invf[m]%mod;
}
int main()
{
    f[0]=f[1]=invf[0]=invf[1]=1;
    for(int i=2;i<N;i++) f[i]=f[i-1]*i%mod,invf[i]=(mod-mod/i)*invf[mod%i]%mod;
    for(int i=2;i<N;i++) invf[i]=invf[i-1]*invf[i]%mod;
    int n,m;
    scanf("%d%d",&n,&m);
    printf("%lld\n",(C(n+m,m)-C(n+m,m-1)+mod)%mod);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值