zoukankan      html  css  js  c++  java
  • BZOJ 1856 [SCOI2010]生成字符串 (组合数)

    题目大意:给你n个1和m个0,你要用这些数字组成一个长度为n+m的串,对于任意一个位置k,要保证前k个数字中1的数量大于等于0的数量,求所有合法的串的数量

    答案转化为所有方案数-不合法方案数

    所有方案数显然是C_{n+m}^{n}

    现在比较易懂的解法是转化进坐标系

    从(0,0)开始,填1视为向右上↗走,填0视为向右下↘走,如果路径经过了y=-1这条直线,说明不合法

    把一个经过y=-1的路径的左半部分(即在路径和y=-1交点之前的那部分路径)关于y=-1翻转

    因为是从(0,0)出发,现在变成了从(0,-2)出发,求方案数,显然是C_{n+m}^{n+1}

    所以最终答案是C_{n+m}^{n}-C_{n+m}^{n+1}

    求逆元即可

     1 #include <queue>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #define N 2000100
     6 #define mod 20100403
     7 #define ll long long 
     8 using namespace std;
     9 
    10 int n,m;
    11 ll mu[N],inv[N];
    12 
    13 void get_mu()
    14 {
    15     mu[0]=mu[1]=inv[0]=inv[1]=1;
    16     for(ll i=2;i<=n+m;i++)
    17         mu[i]=mu[i-1]*i%mod,
    18         inv[i]=(mod-mod/i)*inv[mod%i]%mod;
    19     for(ll i=2;i<=n+m;i++)
    20         inv[i]=inv[i]*inv[i-1]%mod;
    21 }
    22 
    23 int main()
    24 {
    25     scanf("%d%d",&n,&m);
    26     get_mu();
    27     ll ans1=mu[n+m]*inv[n]%mod*inv[m]%mod;
    28     ll ans2=mu[n+m]*inv[n+1]%mod*inv[m-1]%mod;
    29     printf("%lld
    ",(ans1-ans2+mod)%mod);
    30     return 0;
    31 }
  • 相关阅读:
    Redis之分布式锁的使用
    Redis之lua脚本
    Redis 集群的水平扩缩容
    Redis集群搭建及原理
    Redis 的主从、哨兵架构
    CompletableFuture 使用介绍
    Spring Boot 2.x使用H2数据
    pom.xml
    nexus-staging-maven-plugin 踩坑
    安卓Hook折腾研究的笔记记录
  • 原文地址:https://www.cnblogs.com/guapisolo/p/9744645.html
Copyright © 2011-2022 走看看