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 std;
typedef long long ll;
const int N=2e5+20;
const ll mod=1e9+9;
ll n,m,f[N];
ll powmod(ll x,ll n)
{
    ll s=1;
    while(n)
    {
        if(n&1)
            s=(s*x)%mod;
        x=(x*x)%mod;
        n>>=1;
    }
    return s;
}
ll C(ll n,ll m)
{
    ll a=f[n],b=(f[m]*f[n-m])%mod;
    return    (a*powmod(b,mod-2))%mod;
}
int main()
{
    f[0]=1;
    for(ll i=1;i<N;i++)
        f[i]=(f[i-1]*i)%mod;
    while(cin>>n>>m)
    {
        int x,l=0,r=0;
        for(int i=1;i<=n;i++)
        {
            int mn=l;
            scanf("%d",&x);
            if(l>=x)
                l-=x;
            else if(r>=x)//[l~r]
                l=((l%2)==(x%2)?0:1);
            else
                l=x-r;

            if(r+x<=m)
                r+=x;
            else if(mn+x<=m)
                r=((mn+x)%2==(m%2)?m:m-1);
            else
                r=m-(mn+x-m);
        }
        ll ans=0;
    //    cout<<l<<‘ ‘<<r<<endl;
        for(int i=l;i<=r;i+=2)
            ans=(ans+C(m,i))%mod;
        cout<<ans<<endl;
    }
    return 0;
}
时间: 2024-10-07 05:03:04

HDU 4869 Turn The Pokers 思维+组合的相关文章

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 (思维)

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

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 多校训练第一场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

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

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