• Codeforces Round #195 (Div. 2) D题Vasily the Bear and Beautiful Strings


    这场CF,脑子乱死啊。。。C题,搞了很长时间,结束了,才想到怎么做。B题,没看,D题,今天看了一下,很不错的组合题。

    如果n和m都挺多的时候

    以下情况都是变为1,根据偶数个0,最后将会为1,奇数个0,最后变为0,以1开头,全都是0.

    0 1..

    0 0 0 1....

    0 0 0 0 0 1....

    总的情况是C(n+m,m),算1也可以算出来。注意m = 1的时候特判,0的时候,我也全写的特判。

    10^5的组合数,用费马小定理求逆元。看了下题解,题解直接来了个逆元。。

    inv(a) = a^(mod-2),完全没看懂,查了查资料,明白了。。

    a*inv(a) 模 mod = 1

    因为mod是素数,根据费马小定理,a的p-1次方 对 p取余等于1, a^(mod-2)肯定是逆元。

    算组合数,好高端啊。。。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <string>
     4 #include <cmath>
     5 #include <algorithm>
     6 using namespace std;
     7 #define MOD 1000000007
     8 #define LL __int64
     9 LL fact[200101];
    10 LL fastmod(LL a,LL k)
    11 {
    12     LL b = 1;
    13     while(k)
    14     {
    15         if(k&1)
    16         b = a*b%MOD;
    17         a = (a%MOD)*(a%MOD)%MOD;
    18         k = k/2;
    19     }
    20     return b;
    21 }
    22 LL comb(int n,int m)//如果取余是素数,根据费马小定理求逆元,快速求组合数
    23 {
    24     LL ans,a;
    25     ans = fact[n];
    26     a = fastmod((fact[n-m]*fact[m])%MOD,MOD-2);
    27     return (ans*a)%MOD;
    28 }
    29 int main()
    30 {
    31     int i,n,m,g;
    32     LL ans,res;
    33     scanf("%d%d%d",&n,&m,&g);
    34     if(m == 0)
    35     {
    36         if(n%2 == 0)
    37         {
    38             printf("%d
    ",g);
    39         }
    40         else
    41         {
    42             printf("%d
    ",!g);
    43         }
    44         return 0;
    45     }
    46     if(n == 0)
    47     {
    48         if(m == 1&&g == 1)
    49         printf("1
    ");
    50         else if(m == 1&&g == 0)
    51         printf("0
    ");
    52         else if(m > 1&&g == 0)
    53         printf("1
    ");
    54         else
    55         printf("0
    ");
    56         return 0;
    57     }
    58     fact[0] = 1;
    59     for(i = 1;i <= n+m;i ++)
    60     {
    61         fact[i] = (fact[i-1]*i)%MOD;
    62     }
    63     ans = comb(n+m,n);
    64     res = 0;
    65     for(i = 1;i <= n;i += 2)
    66     {
    67         if(m == 0) break;
    68         if(i + 1 == n+m) break;
    69         res = (res + comb(n+m-i-1,m-1))%MOD;
    70     }
    71     if(m == 1&&n%2 == 0)
    72     res ++;
    73     if(g == 1)
    74     printf("%I64d
    ",res);
    75     else
    76     {
    77         ans = (ans - res + MOD)%MOD;
    78         printf("%I64d
    ",ans);
    79     }
    80     return 0;
    81 }
  • 相关阅读:
    如何理解redo和undo的作用
    自建NAS如何使用大于2TB的硬盘(从分区开始)
    Oracle 了解 DDL 操作与 REDO 的关系
    oracle 控制文件的重建
    Oracle 表空间的日常维护与管理
    解决debian 9 重启nameserver失效问题
    Vmware复制完好的linux目录后网卡操作
    RHEL6.X设置163yum源
    【转载】Eclipse快捷键大全
    【转】Java:String、StringBuffer和StringBuilder的区别
  • 原文地址:https://www.cnblogs.com/naix-x/p/3250557.html
Copyright © 2020-2023  润新知