hdu 4869 Turn the pokers (思维)

Turn the pokers

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 196    Accepted Submission(s): 51

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

2014 Multi-University Training Contest 1

题意:

输入操作次数n和扑克牌数m,一开始扑克牌全都背面朝上。现在输入n个数xi,表示每次选择xi张牌翻转,问最后的牌的情况有多少种可能。

思路:

背面为0,正面为1,假设最后能出现x个1,因为每个牌都是一样的,所以最后x个1的情况有C(m,x)个。

现在问题转化为求最后可能出现几个1。

最后的结果奇偶性相同,因为将1个翻转0变为1个翻转1,1的个数会增加2,反之减少2。

最后的结果肯定是一个连续的奇数或者偶数区间,不可能有间断点,原理同上。

现在的任务就是怎样找最大最小值了,如果这次能出现[le,ri]的区间,现在要翻转x次,如果x<=le,那么下次的最小值mi就是le-x了,如果x>le&&x<ri的话,如果le、x同奇偶,mi=0,否则为1,如果x>ri的话,那么mi=x-ri,最大值同理。递推可得到最后的区间。

现在就是要计算C(m,x)了,可以由C(m,0)递推得到,但是涉及到除法,需要用逆元。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#define maxn 235
#define MAXN 100005
#define mod 1000000009
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-8
typedef long long ll;
using namespace std;

ll n,m,ans,flag,cnt,tot;
ll fac[100005],rev[100005];

ll pow_mod(ll a,ll i,ll n)  // 快速幂取模
{
    if(i==0)return 1%n;
    ll temp=pow_mod(a,i>>1,n);
    temp=temp*temp%n;
    if(i&1)temp=temp*a%n;
    return temp;
}
void init() // 初始化
{
    fac[0]=rev[0]=1;
    for(ll i=1;i<=100000;i++)
    fac[i]=fac[i-1]*i%mod,rev[i]=pow_mod(fac[i],mod-2,mod);
}
ll C(ll n,ll m) // 求组合数取mod的值
{
    return (fac[n]*rev[m]%mod)*rev[n-m]%mod;
}

int main()
{
    ll i,j,t,x,le,ri;
    init();
    while(~scanf("%I64d%I64d",&n,&m))
    {
        le=ri=0;
        for(i=1;i<=n;i++)
        {
            scanf("%I64d",&x);
            ll u,v;
            if(x<=le) u=le-x;
            else if(x>le&&x<ri)
            {
                if((x+le)%2==0) u=0;
                else u=1;
            }
            else u=x-ri;

            if(x<=m-ri) v=ri+x;
            else if(x>m-ri&&x<=m-le)
            {
                if((x+le+m)%2==0) v=m;
                else v=m-1;
            }
            else v=le+(m-le)-(x-(m-le));
            le=u,ri=v;
        }
       // printf("le:%I64d ri:%I64d\n",le,ri);
        ans=0;
        for(i=le;i<=ri;i+=2)
        {
            ans+=C(m,i);
            ans%=mod;
        }
        printf("%I64d\n",ans);
    }
    return 0;
}

hdu 4869 Turn the pokers (思维),布布扣,bubuko.com

时间: 2024-10-05 23:58:39

hdu 4869 Turn the pokers (思维)的相关文章

HDU 4869 Turn The Pokers 思维+组合

HDU 4869题意:m张牌,朝上状态为1,朝下状态为0,现在有n个操作 第i次操作可以反转任意xi张牌初始牌全部朝下,n,m<=1e5,问n次操作后能得到多少种不同的状态? 关心的是最后的状态 假如1有x个 则贡献C(m,x)种状态因为每翻转一次,1的个数和0的个数都相差2. 当每轮最少得到x个1,最多得到y个1 则1的个数范围[x,x+2...y-2,y]中都能取到,维护1的可取个数 组合数累加即可. #include <bits/stdc++.h> using namespace

HDU 4869 Turn the pokers(思维+逆元)

考试的时候没有做出来... 想到了答案一定是一段连续的区间,一直在纠结BFS判断最后的可行1数. 原来直接模拟一遍就可以算出来最后的端点... 剩下的就是组合数取模了,用逆元就行了... # include <cstdio> # include <cstring> # include <cstdlib> # include <iostream> # include <vector> # include <queue> # includ

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:0

HDU 4869 Turn the pokers(推理)

HDU 4869 Turn the pokers 题目链接 题意:给定n个翻转扑克方式,每次方式相应能够选择当中xi张进行翻转.一共同拥有m张牌.问最后翻转之后的情况数 思路:对于每一些翻转,假设能确定终于正面向上张数的情况,那么全部的情况就是全部情况的C(m, 张数)之和.那么这个张数进行推理会发现,事实上会有一个上下界,每隔2个位置的数字就是能够的方案,由于在翻牌的时候,相应的肯定会有牌被翻转,而假设向上牌少翻一张,向下牌就要多翻一张.奇偶性是不变的,因此仅仅要每次输入张数,维护上下界,最后

hdu 4869 Turn the pokers(递推&amp;组合数学&amp;逆元)

Turn the pokers Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1279    Accepted Submission(s): 466 Problem Description During summer vacation,Alice stay at home for a long time, with nothing t

hdu 4869 Turn the pokers(数学)

题目链接:hdu 4869 Turn the pokers 题目大意:给定n和m,表示有n次翻牌的机会,m张牌,一开始所有的牌均背面朝上,每次翻牌可以选择xi张牌同时翻转.问说最后有多少种能. 解题思路:只要确定最后正面朝上的牌的个数即可.所以在读入xi的时候维护上下限即可. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long l

2014多校第一场 I 题 || HDU 4869 Turn the pokers(费马小定理+快速幂模)

题目链接 题意 : m张牌,可以翻n次,每次翻xi张牌,问最后能得到多少种形态. 思路 :0定义为反面,1定义为正面,(一开始都是反), 对于每次翻牌操作,我们定义两个边界lb,rb,代表每次中1最少时最少的个数,rb代表1最多时的个数.一张牌翻两次和两张牌翻一次 得到的奇偶性相同,所以结果中lb和最多的rb的奇偶性相同.如果找到了lb和rb,那么,介于这两个数之间且与这两个数奇偶性相同的数均可取到,然后在这个区间内求组合数相加(若lb=3,rb=7,则3,5,7这些情况都能取到,也就是说最后的

HDU 4869 Turn the pokers 逆元

题解地址:点击打开链接 题解:最终的结果一定是连续出现的,只需要求出最终的区间.因为如果对同一张牌进行两次操作,牌的状态不改变.故牌的翻转次数一定是减少偶数次.如果所有数的和是奇数,那么最终结果也一定是奇数.同理,偶数也是一样的.所以只要递推求出最后的区间,计算sum(C(xi,m)(i=0,1,2...)),m是总牌数,xi是在区间内连续的奇数或偶数,在模10^9+9就是最终的答案. #include <stdio.h> #include <string.h> #include

HDU 4869 Turn the pokers 多校训练第一场1009

Turn the pokers Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 282    Accepted Submission(s): 89 Problem Description During summer vacation,Alice stay at home for a long time, with nothing to