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