设牌的正面为1,反面为0,则每翻一张牌就会使1的个数变更1,故不同的翻法之间1的个数相差0或2。得出结论:1、最后结果中的1的个数的奇偶性取决于所有翻牌数目之和的奇偶性。2、可能结果一定是连续间隔2的。
故只要找出1可能个数的最小值mi和最大值ma,就可以知道1的所有可能值,然后求C(m,i)之和取模就好了。
到第i次翻牌时,如果mi>=a[i],则mi=mi-a[i];否则如果ma>=a[i],a[i]和mi奇偶性相同时mi为0,不同时为1;否则mi=a[i]-ma;
求最大值类似。
#include<iostream>
#include<cstdio>
#define ll long long
#define p 1000000009
#define N 100010
using namespace std;
ll fac[N];
void init()
{
int i;
fac[0] =1;
for(i =1; i <= 100000; i++)
fac[i] = fac[i-1]*i % p;
}
ll pow(ll a, ll b)
{
ll tmp = a % p, res =1;
while(b)
{
if(b &1) res = res * tmp % p;
tmp = tmp*tmp % p;
b >>=1;
}
return res;
}
ll C(ll n, ll m)
{
if(m > n) return 0;
return fac[n]*pow(fac[m]*fac[n-m], p-2) % p;
}
int main()
{
//freopen("1.in","r",stdin);
ll n,m;
init();
while(scanf("%I64d%I64d",&n,&m)!=EOF)
{
ll mi=0,ma=0,x;
for(int i=0;i<n;i++)
{
scanf("%I64d",&x);
int u=mi;
if(x<=mi)mi-=x;
else if(x<=ma)mi=(mi%2)^(x%2);
else mi=x-ma;
if(x<=m-ma)ma+=x;
else if(x<=m-u)ma=m-((m%2)^((u+x)%2));
else ma=2*m-u-x;
}
ll ans=0;
for(ll i=mi;i<=ma;i+=2)ans=(ans+C(m,i))%p;
printf("%I64d\n",ans);
}
return 0;
}