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\n", 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 }
官方题解的解组合
posted @ 2014-07-23 21:58  GLSilence  阅读(301)  评论(0编辑  收藏  举报