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)

    思路:要说清楚不是非常easy。官方题解是这么说的:

    “终于的结果一定是连续出现的,仅仅须要求出终于的区间。

    由于假设对同一张牌进行两次操作,牌的状态不改变。故牌的翻转次数一定是降低偶数次。假设全部数的和是奇数,那么终于结果也一定是奇数。同理,偶数也是一样的。

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

    #define LL long long
    
    const int MOD = 1000000009;
    LL J[100005];
    
    void Init()
    {///初始化阶乘表
        J[0] = 1;
        for(int i = 1; i <= 100005; ++i){
            J[i] = J[i-1]*i%MOD;
        }
    }
    
    ///高速幂取模
    LL modexp(LL a,LL b,LL n)
    {
        LL ret=1;
        LL tmp=a;
        while(b)
        {
           if(b&1) ret=ret*tmp%n;
           tmp=tmp*tmp%n;
           b>>=1;
        }
        return ret;
    }
    ///求组合数 逆元 C(n, m) = n! * (m!*(n-m)!)^(MOD-2)
    LL C(LL n, LL m)
    {
        return J[n]*modexp(J[m]*J[n-m]%MOD, MOD-2, MOD)%MOD;
    }
    
    int a[100010];
    
    int main()
    {
        int n, m;
        Init();
        while(~scanf("%d%d", &n, &m))
        {
            for(int i = 0; i < n; ++i)
            {
                scanf("%d", &a[i]);
            }
            int l = 0;
            int r = 1;
            int t = 0;
            for(int i = 0; i < n; ++i)
            {
                int ll = min(abs(l-a[i]), abs(r-a[i]));
                if(l <= a[i] && r >= a[i])
                {
                    ll = 0;
                }
                int rr = max(m-abs(l+a[i]-m), m-abs(r+a[i]-m));
                if(l <= m-a[i] && r >= m-a[i])
                {
                    rr = m;
                }
    
                t = (t+a[i])%2;
                l = ll;
                r = rr;
            }
            long long ans = 0;
            for(int i = l; i <= r; ++i)
            {
                if(i%2 == t)
                {
                    ans += C(m, i);
                    ans %= MOD;
                }
            }
            printf("%I64d
    ", ans);
        }
    
        return 0;
    }
    


    //官方题解的解组合
    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    #include<cmath>
    using namespace std;
    int a[100005];
    __int64 pmod = 1000000009;
    __int64 inv[100005];
    __int64 ba[100005];
    __int64 rba[100005];
    #define M 100005
    void pre() {
    	inv[0] = inv[1] = 1;
    	ba[0] = ba[1] = 1;
    	rba[0] = rba[1] = 1;
    	for (int i = 2; i < M; i++) {
    		inv[i] = ((pmod - pmod / i) * inv[pmod % i]) % pmod;
    		ba[i] = (ba[i - 1] * i)%pmod;
    		rba[i] = (rba[i - 1] * inv[i])%pmod;
    	}
    }
    __int64 C(int n, int k) {
    	return (ba[n] * rba[k] % pmod )* rba[n - k] % pmod;
    }


  • 相关阅读:
    【HDOJ6667】Roundgod and Milk Tea(模拟)
    【HDOJ6655】Just Repeat(贪心)
    【HDOJ6651】Final Exam(贪心)
    【HDOJ6646】A + B = C(模拟)
    【HDOJ6656】Kejin Player(期望DP)
    【2019 Multi-University Training Contest 7】
    【HDOJ6635】Nonsense Time(时间倒流,lis)
    【HDOJ6638】Snowy Smile(线段树)
    【HDOJ6641】TDL(数论)
    【HDOJ6645】Stay Real(堆)
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/5143249.html
Copyright © 2011-2022 走看看