首页 > 代码库 > 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 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;
}

 

HDU 4869 Turn The Pokers 思维+组合