HDU 4869 Turn the pokers(瞎搞+逆元快速幂)

多校第一场,被惨虐。还是水平太差,多补题啊!

题意很好理解,主要是想明白不太好想。

题解博客:http://blog.sina.com.cn/s/blog_6bddecdc0102uy9g.html

题解上写的也算比较清晰:最终的结果一定是连续出现的,只需要求出最终的区间。
因为如果对同一张牌进行两次操作,牌的状态不改变。故牌的翻转次数一定是减少偶数次。如果所有数的和是奇数,那么最终结果也一定是奇数。同理,偶数也是一样的。
所以只要递推求出最后的区间,计算sum(C(xi,m)(i=0,1,2。。。)),m是总牌数,xi是在区间内连续的奇数或偶数,在模10^9+9就是最终的答案。

数据比较大需要用逆元然后求快速幂。

C(n, m) = m!/(m-n)!*n!

快速计算组合数对MOD取余:

C(n, m)%MOD = (m!%MOD)*(n!%MOD*(m-n)!%MOD)^(MOD-2)%MOD。需要用到快速幂取模。

还有就是在找区间的时候一定要注意边界,左边不能小于0,右边不得越过m。

Turn the pokers

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 149    Accepted Submission(s): 32


Problem Description
During summer vacation,Alice stay at home for a long time, with nothing to do. She went out and bought m pokers, tending to play poker. But she hated the traditional gameplay. She wants to change. She puts these pokers face down, she decided to flip poker n times, and each time she can flip Xi pokers. She wanted to know how many the results does she get. Can you help her solve this problem?
 

Input
The input consists of multiple test cases. 
Each test case begins with a line containing two non-negative integers n and m(0<n,m<=100000). 
The next line contains n integers Xi(0<=Xi<=m).
 

Output
Output the required answer modulo 1000000009 for each test case, one per line.
 

Sample Input
  
  
3 4 3 2 3 3 3 3 2 3
 

Sample Output
  
  
8 3
Hint
For the second 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)
 

Source
#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <iomanip>
#include <stdio.h>
#include <string>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <set>
#define eps 1e-7
#define M 10001000
//#define LL __int64
#define LL long long
#define INF 0x3f3f3f3f
#define PI 3.1415926535898
#define MOD 1000000009
const int maxn = 100010;

using namespace std;

int num[maxn];
LL f[maxn];

void Del()
{
    f[0] = 1;
    for(int i = 1; i <= maxn-5; i++)
        f[i] = (f[i-1]*i)%MOD;
}
/*
LL modmul(LL a, LL b)
{
    LL res = 0;
    LL tmp = a;
    while(b)
    {
        if(b&1) res = (res+tmp)%MOD;
        tmp = (tmp+tmp)%MOD;
        b >>= 1;
    }
    return res;
}

LL modexp(LL a, LL b)
{
    LL res = 1;
    LL tmp = a;
    while(b)
    {
        if(b&1) res = modmul(res, tmp);
        tmp = modmul(tmp, tmp);
        b >>= 1;
    }
    return res;
}*/
LL fastmod(LL a, LL k)
{
    LL b = 1;
    while(k)
    {
        if(k&1)
            b = a*b%MOD;
        a = (a%MOD)*(a%MOD)%MOD;
        k = k/2;
    }
    return b;
}
int main()
{
    int n, m;
    Del();
    while(~scanf("%d %d",&n, &m))
    {
        scanf("%d",&num[1]);
        int l = num[1];
        int r = num[1];
        for(int i = 2; i <= n; i++)
        {
            scanf("%d",&num[i]);
            int ll = l-num[i];
            int rr = r+num[i];
            if(ll < 0)
            {
                if(r-num[i] < 0) ll = num[i]-r;
                else ll = ((l-num[i])%2+2)%2;
            }
            if(rr > m)
            {
                if(l+num[i] <= m) rr = m-(r+num[i])%2;
                else rr = m-(l+num[i]-m);
            }
            l = ll;
            r = rr;
        }
        LL cnt = 0;
        for(int i = l; i <= r; i += 2)
            cnt += ((f[m]%MOD)*(fastmod((f[i]*f[m-i])%MOD, MOD-2)))%MOD;
        cout<<(cnt%MOD)<<endl;
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值