zoukankan      html  css  js  c++  java
  • [数论] 洛谷 P1641 生成字符串

    题目描述

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

    输入输出格式

    输入格式:

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

    输出格式:

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

    输入输出样例

    输入样例#1:
    2 2
    输出样例#1:
    2

    说明

    limitation

    每点2秒

    对于30%的数据,保证1<=m<=n<=1000

    对于100%的数据,保证1<=m<=n<=1000000

    题解

    • 对于这题,我们可以考虑将全部的方案-不合法的方案=合法的方案
    • 先来考虑一下全部的方案,字符串的长度为n+m,在里面放n个1,方案数就是C(n+m,n)
    • 那么怎么求出不合法的情况的方案呢
    • 我们把放0、1当做是在平面直角坐标系上,放1就当做是(+1,+1),放0就当做是(+1,-1)那么当直线到达(x,-1)时,就是不合法的
    • 然后我们把y=-1当做是对称轴,将我们形成的直线对称下来,然后我们可以发现其实就是从(0,-2)开始到达(n+m,n-m)的方案数就是不合法滴
    • 最后的话,答案就是C(n+m,n)-C(n+m,m-1)

    代码

     1 #include <iostream>
     2 #include <cstdio>
     3 #define ll long long
     4 using namespace std;
     5 const ll mo=20100403;
     6 ll n,m,p[2000050],q[2000050];
     7 ll C(ll x,ll y) { return q[x]*p[y]%mo*p[x-y]%mo; }
     8 int main()
     9 {
    10     scanf("%lld%lld",&n,&m),p[0]=p[1]=q[0]=q[1]=1;;
    11     for (ll i=2;i<=n+m;i++) p[i]=(mo-mo/i)*p[mo%i]%mo,q[i]=q[i-1]*i%mo;
    12     for (ll i=2;i<=n+m;i++) p[i]=p[i-1]*p[i]%mo;
    13     printf("%lld",((C(n+m,m)-C(n+m,m-1))%mo+mo)%mo);
    14     return 0;
    15 }
  • 相关阅读:
    MSSQL大量数据时,建立索引或添加字段后保存更改超时该这么办
    POJ 3261 Milk Patterns (后缀数组)
    POJ 1743 Musical Theme (后缀数组)
    HDU 1496 Equations (HASH)
    694. Distinct Substrings (后缀数组)
    POJ 1222 EXTENDED LIGHTS OUT (枚举 或者 高斯消元)
    POJ 1681· Painter's Problem (位压缩 或 高斯消元)
    POJ 1054 The Troublesome Frog (hash散列)
    HDU 1716 排列2
    HDU 4405 Aeroplane chess (概率DP & 期望)
  • 原文地址:https://www.cnblogs.com/Comfortable/p/10324738.html
Copyright © 2011-2022 走看看