zoukankan      html  css  js  c++  java
  • HDU 4869 Turn the pokers(思维+组合公式+快速幂)

    Turn the pokers

    大意:给出n次操作,给出m个扑克,然后给出n个操作的个数a[i],每个a[i]代表可以翻的扑克的个数,求最后可能出现的扑克的组合情况。

    Hint

    Sample Input:

    3 3

    3 2 3

    For the this example:

    0 express face down,1 express face up

    Initial state 000

    The first result:000->111->001->110

    The second result:000->111->100->011

    The third result:000->111->010->101

    So, there are three kinds of results(110,011,101)

    思路:要说清楚不是很容易。官方题解是这么说的:

    “最终的结果一定是连续出现的,只需要求出最终的区间。

    因为如果对同一张牌进行两次操作,牌的状态不改变。故牌的翻转次数一定是减少偶数次。如果所有数的和是奇数,那么最终结果也一定是奇数。同理,偶数也是一样的。

    所以只要递推求出最后的区间,计算sumCxim)(i=012。。。)),m是总牌数,xi是在区间内连续的奇数或偶数,在模10^9+9就是最终的答案。”

     1 #define LL long long
     2 
     3 const int MOD = 1000000009;
     4 LL J[100005];
     5 
     6 void Init()
     7 {///初始化阶乘表
     8     J[0] = 1;
     9     for(int i = 1; i <= 100005; ++i){
    10         J[i] = J[i-1]*i%MOD;
    11     }
    12 }
    13 
    14 ///快速幂取模
    15 LL modexp(LL a,LL b,LL n)
    16 {
    17     LL ret=1;
    18     LL tmp=a;
    19     while(b)
    20     {
    21        if(b&1) ret=ret*tmp%n;
    22        tmp=tmp*tmp%n;
    23        b>>=1;
    24     }
    25     return ret;
    26 }
    27 ///求组合数 逆元 C(n, m) = n! * (m!*(n-m)!)^(MOD-2)
    28 LL C(LL n, LL m)
    29 {
    30     return J[n]*modexp(J[m]*J[n-m]%MOD, MOD-2, MOD)%MOD;
    31 }
    32 
    33 int a[100010];
    34 
    35 int main()
    36 {
    37     int n, m;
    38     Init();
    39     while(~scanf("%d%d", &n, &m))
    40     {
    41         for(int i = 0; i < n; ++i)
    42         {
    43             scanf("%d", &a[i]);
    44         }
    45         int l = 0;
    46         int r = 1;
    47         int t = 0;
    48         for(int i = 0; i < n; ++i)
    49         {
    50             int ll = min(abs(l-a[i]), abs(r-a[i]));
    51             if(l <= a[i] && r >= a[i])
    52             {
    53                 ll = 0;
    54             }
    55             int rr = max(m-abs(l+a[i]-m), m-abs(r+a[i]-m));
    56             if(l <= m-a[i] && r >= m-a[i])
    57             {
    58                 rr = m;
    59             }
    60 
    61             t = (t+a[i])%2;
    62             l = ll;
    63             r = rr;
    64         }
    65         long long ans = 0;
    66         for(int i = l; i <= r; ++i)
    67         {
    68             if(i%2 == t)
    69             {
    70                 ans += C(m, i);
    71                 ans %= MOD;
    72             }
    73         }
    74         printf("%I64d
    ", ans);
    75     }
    76 
    77     return 0;
    78 }
    自己写的
     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<iostream>
     4 #include<cmath>
     5 using namespace std;
     6 int a[100005];
     7 __int64 pmod = 1000000009;
     8 __int64 inv[100005];
     9 __int64 ba[100005];
    10 __int64 rba[100005];
    11 #define M 100005
    12 void pre() {
    13     inv[0] = inv[1] = 1;
    14     ba[0] = ba[1] = 1;
    15     rba[0] = rba[1] = 1;
    16     for (int i = 2; i < M; i++) {
    17         inv[i] = ((pmod - pmod / i) * inv[pmod % i]) % pmod;
    18         ba[i] = (ba[i - 1] * i)%pmod;
    19         rba[i] = (rba[i - 1] * inv[i])%pmod;
    20     }
    21 }
    22 __int64 C(int n, int k) {
    23     return (ba[n] * rba[k] % pmod )* rba[n - k] % pmod;
    24 }
    官方题解的解组合
  • 相关阅读:
    C++ ORM ODB 入门(三)
    C++ ORM ODB 入门介绍(二)
    最简便的MySql数据库备份方法
    快速高效的破解MySQL本地和远程密码
    C++ ORM ODB 入门介绍(一)
    NeHe OpenGL教程 第三十九课:物理模拟
    NeHe OpenGL教程 第三十八课:资源文件
    NeHe OpenGL教程 第三十七课:卡通映射
    NeHe OpenGL教程 第三十六课:从渲染到纹理
    NeHe OpenGL教程 第三十五课:播放AVI
  • 原文地址:https://www.cnblogs.com/Silence-AC/p/3864103.html
Copyright © 2011-2022 走看看