• 【SCOI2010】生成字符串


    Description

    给定n,m,求一个包含n个1,m个0,且任何前缀的1的数量必须大于0的数量的合法01串的数量,答案对20100403取模。

    Solution

    我们建立坐标系,定义x坐标为1和0的数量的和,y坐标表示1和0的数量的差,那么向右上走就表示选择1,向右下走就表示选择0。

    如果不考虑限制条件,那么我们要从(0,0)走到(n+m,n-m),就相当于从n+m步中选出m步向右下走,方案数就是$C_{n+m}^m$

    现在考虑限制条件:任何前缀的1的数量必须大于0的数量,那么就意味着我们的在坐标系中的路径不能经过直线y=-1,那么非法的方案就是从(0,0)走到(x,-1)再走到(n+m,n-m),这就等价于从(0,-2)开始走到(n+m,n-m),即方案数为$C_{n+m}^{m-1}$,那么合法方案数就是这两个方案数之差。

    我们首先预处理出一个阶乘数组和一个阶乘的逆元数组,逆元可以通过费马小定理或者是线性递推实现。

    然后套用组合数的公式即可完成。

    Code

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 ll n, m, fac[2000010], inv[2000010];
     5 const ll mod = 20100403;
     6 inline ll qpow(ll a, ll n) {
     7     ll ret = 1;
     8     while (n) {
     9         if (n & 1) ret = (ret * a) % mod;
    10         a = a * a % mod;
    11         n >>= 1;
    12     }
    13     return ret;
    14 }
    15 inline ll C(ll n, ll m) {
    16     return ((fac[n] * inv[m]) % mod) * inv[n - m] % mod;
    17 }
    18 int main() {
    19     scanf("%lld%lld", &n, &m);
    20     fac[1] = 1;
    21     for (register int i = 2; i <= n + m; ++i) fac[i] = fac[i - 1] * i % mod;
    22     for (register int i = 1; i <= n + m; ++i) inv[i] = qpow(fac[i], mod - 2);
    23     printf("%lld
    ", (C(n + m, m) - C(n + m, m - 1) + mod) % mod);
    24     return 0;
    25 }
    AC Code
  • 相关阅读:
    CSS3笔记!
    Charles与Jmeter结合编写接口测试
    Charles测试点集锦
    pom文件报错关于maven-compiler-plugin:3.1
    Jmeter获取数据库值并作为参数请求(转载)
    mysql基础操作语言
    JMeter之Ramp-up Period(in seconds)说明
    Jmeter查看QPS和响应时间随着时间的变化曲线(转载)
    Charles篡改后台数据
    接口测试之——Charles抓包及常见问题解决(转载自https://www.jianshu.com/p/831c0114179f)
  • 原文地址:https://www.cnblogs.com/shl-blog/p/11295818.html
Copyright © 2020-2023  润新知