BZOJ1856 字符串

题目描述

lxhgww最近接到了一个生成字符串的任务,任务需要他把n个1和m个0组成字符串,但是任务还要求在组成的字符串中,在任意的前k个字符中,1的个数不能少于0的个数。现在lxhgww想要知道满足要求的字符串共有多少个,聪明的程序员们,你们能帮助他吗?

解析:

这道题非常有意思,凝聚了组合数学和数形结合的思想,在处理的过程中还要用到乘法逆元。我们可以把它转化到一张网格图上,对于每次选0或选1,我们可以让他对应每次向右下或右上走,那么走到(n,n-m)的方案有多少种。考虑到不能让某一时刻的0的个数比1多,我们只需减去经过y=-1的方案数即可对于不合法的方案,把第一次碰到y=-1之前的折线翻折一下可以看成从(-2,0)走到(n+m,n-m)的方案数,即 C(n+m,m)-C(n+m,m-1)

#include <iostream>
#include <cstdio>
#define ll long long
using namespace std;
const ll N=20100403;
ll n,m,tot,unf,ans;
inline ll read()
{
    ll f=1,x=0;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
    return f*x;
}
inline ll pow(ll x,ll y)
{
    if (y==0) return 1;
    ll k=1;
    while (y)
    {
        if (y&1) k=k*x%N;
        y/=2;
        x=x*x%N;
    }
    return k;
}
int main()
{
    n=read();m=read();
    tot=unf=1;
    for (ll i=m+1;i<=n+m;i++)
        tot=tot*i%N*pow(i-m,N-2)%N;
    for (ll i=m;i<=n+m;i++)
        unf=unf*i%N*pow(i-m+1,N-2)%N;
    ans=((tot-unf)%N+N)%N;
    printf("%lld",ans);
    return 0;
}

代码:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值