1. 程式人生 > >HDU 4869 Turn The Pokers 思維+組合

HDU 4869 Turn The Pokers 思維+組合

+= hdu 累加 color bsp 相差 while ... 1的個數


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 思維+組合