• 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

      题解:很明显可以抽象成卡特兰数的表达式,即从(0,0)点走到(n,m)点,但是不能越过y=x这条线的方案数,方案数为**$C_{n+m}^{m}-C_{n+m}^{m-1}$;
      我用了两个做法。。先是用逆元做了一次,有用Lucas定理做了一次,直接把组合数化简/套用定理+快速幂即可.  
    逆元代码:(写得丑就这么看吧……应该能看懂)
     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 using namespace std;
     5 const int MAXN=1000001;
     6 const long long mod=20100403;
     7 long long tot=1,temp=1;
     8 long long ksm(long long a,long long b,long long c)
     9 {
    10     long long ans=1;
    11     while(b!=0)
    12     {
    13         if(b%2==1) ans=ans*a%c;
    14         a=a*a%c;
    15         b/=2;
    16     }
    17     return ans%c;
    18 }
    19 int main(int argc, char *argv[])
    20 {
    21     long long n,m,i,j,nn,mm;
    22     scanf("%lld%lld",&n,&m);
    23     nn=n,mm=n;
    24     for(i=n+m;i>n;i--)
    25     tot=tot*i%mod;
    26     for(i=1;i<=m;i++)
    27     temp=temp*i%mod;
    28     long long k=ksm(temp,mod-2,mod);
    29     tot=tot*k%mod;
    30     temp=1;
    31     for(i=n+m;i>=n+2;i--)
    32     temp=temp*i%mod;
    33     long long tempt=1;
    34     for(i=1;i<m;i++)
    35     tempt=tempt*i%mod;
    36     k=ksm(tempt,mod-2,mod);
    37     tot=(tot-k*temp%mod+mod)%mod;
    38     printf("%lld
    ",tot);
    39     return 0;
    40 }
    Lucas代码:
     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 using namespace std;
     5 const int mod=20100403;
     6 long long n,m,p;
     7 long long quick_pow(long long a,long long b,long long c)
     8 {
     9     long long ans=1;
    10     while(b!=0)
    11     {
    12         if(b%2==1) ans=ans*(a%c)%c;
    13         a=a%c*a%c;
    14         b/=2;
    15     }
    16     if(b==0) return ans%c;
    17 }
    18 long long C(long long n,long long m,long long p)
    19 {
    20     long long a=1,b=1;
    21     if(m>n) return 0;
    22     while(m>0)
    23     {
    24         a=a*n%p;
    25         b=b*m%p;
    26         m--;
    27         n--;
    28     }
    29     return a*quick_pow(b,p-2,p)%p;
    30 }
    31 long long Lucas(long long n,long long m,long long p)
    32 {
    33     if(m==0) return 1;
    34     return (C(n%p,m%p,p)*Lucas(n/p,m/p,p)%p);
    35 }
    36 int main(int argc, char *argv[])
    37 {
    38     scanf("%d%d",&n,&m);
    39     long long ans=Lucas(n+m,m,mod);
    40     ans=(ans-Lucas(n+m,m-1,mod)+mod)%mod;
    41     printf("%lld
    ",ans);
    42     return 0;
    43 }
  • 相关阅读:
    2-用EasyNetQ连接RabbitMQ(黄亮翻译)
    1-EasyNetQ介绍(黄亮翻译)
    MVC之——Razor语法
    MVC过滤器的用法
    MVC初级知识之——Routing路由
    MVC初级知识之——View与Controller的讲解
    MVC初级教程(四)
    MVC初级教程(三)
    MVC初级教程(二)
    MVC初级教程(一)
  • 原文地址:https://www.cnblogs.com/BeyondW/p/5832094.html
Copyright © 2020-2023  润新知