zoukankan      html  css  js  c++  java
  • 题解 P1641 【[SCOI2010]生成字符串】

    题目链接

    Solution [SCOI2010]生成字符串

    题目大意:询问在(n)(1)(m)(0)排列形成的字符串中,有多少个字符串任意前缀中(1)的个数不少于(0)的个数

    卡特兰数


    看到题面很容易想到卡特兰数,这里用与之类似的证明思路

    首先(n)(1)(m)(0)组成的字符串有(C_{n + m}^{n})个(有(n+m)个位置,填了(n)(1)自然(0)的位置就确定了)

    我们减去不合法的字符串,存在任意前缀使得(0)数量大于(1)

    假如有这种字符串的话,一定存在一个位置(2p+1 in [1,n+m]),使得前(2p+1)个数字里面有(p+1)(0),(p)(1),那么后面有(n-p)(1)(m-p-1)(0),对后面取反有(n-p)(0)(m-p-1)(1),所以我们得到了有(n+1)(0)(m-1)(1)的序列

    同理,对于一个由(n+1)(0)(m-1)(1)组成的序列,我们也可以用同样的方法得到有(n)(1),(m)(0)的序列

    也就是说这两种序列构成一个双射,即不合法序列的数量就是由(n+1)(0)(m-1)(1)组成的序列数量

    所以答案(C_{n+m}^{n}-C_{n+m}^{n+1}),直接暴力求就好了

    #include <cstdio>
    using namespace std;
    const int mod = 20100403;
    typedef long long ll;
    inline ll fac(ll x){
    	ll res = 1;
    	for(ll i = 1;i <= x;i++)res = (res * i) % mod;
    	return res;
    }
    inline ll qpow(ll a,ll b){
    	a %= mod;
    	ll base = a,res = 1;
    	while(b){
    		if(b & 1)res = (res * base) % mod;
    		base = (base * base) % mod;
    		b >>= 1;
    	}
    	return res;
    }
    inline ll inv(ll x){return qpow(x,mod - 2);}
    inline ll mul(ll a,ll b){return (a * b) % mod;}
    inline ll C(ll n,ll m){return m > n ? 0 : mul(mul(fac(n),inv(fac(m))),inv(fac(n - m)));}
    int n,m;
    int main(){
    	scanf("%d %d",&n,&m);
    	printf("%lld
    ",(C(n + m,n) - C(n + m,n + 1) + mod) % mod);
    	return 0;
    }
    
  • 相关阅读:
    管理员必备的Linux系统监控工具
    kafka入门:简介、使用场景、设计原理、主要配置及集群搭建(转)
    RedHat linux配置yum本地资源
    RedHat Linux RHEL6配置本地YUM源
    c语言中的fgets函数
    sprintf()函数的用法
    spring boot整合JWT例子
    spring boot 自定义过滤器链
    (转)ArrayList和LinkedList的几种循环遍历方式及性能对比分析
    (转)Springboot 中filter 注入对象
  • 原文地址:https://www.cnblogs.com/colazcy/p/11721062.html
Copyright © 2011-2022 走看看