zoukankan      html  css  js  c++  java
  • BZOJ1856: [Scoi2010]字符串

    Description

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

    Input

    输入数据是一行,包括2个数字n和m

    Output

    输出数据是一行,包括1个数字,表示满足要求的字符串数目,这个数可能会很大,只需输出这个数除以20100403的余数

    Sample Input

    2 2

    Sample Output

    2

    HINT

    【数据范围】
    对于30%的数据,保证1<=m<=n<=1000
    对于100%的数据,保证1<=m<=n<=1000000

    蒟蒻表示只会nk的DP,承担不起
    根据题解考虑转化模型,变为从(0,0)走到(n+m,n-m),1表示斜向上走比如(0,0)走到(1,1),0则相反
    那么总数为C(n+m,m),再考虑错误情况
    那就是走到过-1的这些情况,那么对-1取对称,其实就是跑了y轴中-2往上的情况
    走到(n+m,n-m)需要向上走n-m+2次,一共要走n+m次。设向上向下各走x,y,
    那么x+y=n+m,x-y=n-m+2得到x=n+1,y=m-1,所以不合法的方案为C(n+m,m-1)
    实力太弱实在无力
    代码如下:
    //MT_LI
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    ll mod=20100403ll;
    int n,m;
    ll pow_mod(ll a,ll b)
    {
        ll ans=1ll;
        while(b)
        {
            if(b&1)ans=ans*a%mod;
            b/=2;a=a*a%mod;
        }
        return ans;
    }
    ll fac[2100000];
    void init()
    {
        fac[1]=1ll;
        for(ll i=2;i<=2000000;i++)
            fac[i]=fac[i-1]*i%mod;
    }
    int main()
    {
        init();
        scanf("%d%d",&n,&m);
        printf("%lld
    ",(fac[n+m]*pow_mod(fac[n],mod-2)%mod*pow_mod(fac[m],mod-2)%mod-fac[n+m]*pow_mod(fac[m-1],mod-2)%mod*pow_mod(fac[n+1],mod-2)%mod+mod)%mod);
        return 0;
    }
  • 相关阅读:
    java+opencv实现图像灰度化
    java实现高斯平滑
    hdu 3415 单调队列
    POJ 3368 Frequent values 线段树区间合并
    UVA 11795 Mega Man's Mission 状态DP
    UVA 11552 Fewest Flops DP
    UVA 10534 Wavio Sequence DP LIS
    UVA 1424 uvalive 4256 Salesmen 简单DP
    UVA 1099 uvalive 4794 Sharing Chocolate 状态DP
    UVA 1169uvalive 3983 Robotruck 单调队列优化DP
  • 原文地址:https://www.cnblogs.com/MT-LI/p/9869753.html
Copyright © 2011-2022 走看看