Turn the pokers
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 625 Accepted Submission(s): 220
Problem Description
During summer vacation,Alice stay at home for a long time, with nothing to do. She went out and bought m pokers, tending to play poker. But she hated the traditional gameplay. She wants to change. She puts these pokers face down, she decided to flip poker n times, and each time she can flip Xi pokers. She wanted to know how many the results does she get. Can you help her solve this problem?
Input
The input consists of multiple test cases.
Each test case begins with a line containing two non-negative integers n and m(0<n,m<=100000).
The next line contains n integers Xi(0<=Xi<=m).
Each test case begins with a line containing two non-negative integers n and m(0<n,m<=100000).
The next line contains n integers Xi(0<=Xi<=m).
Output
Output the required answer modulo 1000000009 for each test case, one per line.
Sample Input
3 4 3 2 3 3 3 3 2 3
Sample Output
8 3HintFor the second example: 0 express face down,1 express face up Initial state 000 The first result:000->111->001->110 The second result:000->111->100->011 The third result:000->111->010->101 So, there are three kinds of results(110,011,101)
有m个扑克牌,初始全部背面朝上有n个操作,每个操作可以同时对xi张牌反转,问最后有多少种情况。
首先,反转的总数是奇数那么最后的正面朝上的一定是奇数张,反转的结果与反转的顺序唔关,反转距有任意性,所以我们只需要关注最后结果可以有多少张正面朝上。
我们定义两个变量l,r分别记录结果正面朝上的最少可以有多少张,最多可以有多少张,然后没输入一次操作,对l,r进行更新。然后可能性相隔总是为2,而且是连续的,比如l=0,r=4,那么1,3肯定是不可以的,2肯定是可以的。因为如果改变翻转一张牌,去翻另一张,相当于改变了两张牌,正面朝上的张数就是加2或者不变或者减2,所以可能性也就连续。
然后用个oe来记录操作总和的奇偶性,最后求sigma(C(m,i))%MOD就是答案,这里求C(m,i)的时候用到逆元,可以用递推式inv[i]=(M-M/i)*inv[M%i]%M,(M=MOD),也可以用费马小定理或者扩展欧几里得算。
#include <iostream>
#include <cmath>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <cstring>
#include <map>
#include <string>
#include <queue>
using namespace std;
#define LL long long
#define REP(i,a,b) for(int i=a;i<=b;++i)
#define mset(a) memset(a,0,sizeof a)
#define FR(a) freopen(a,"r",stdin)
#define FW(a) freopen(a,"w",stdout)
#define PI 3.141592654
#define scan(a) scanf("%d",&a)
const LL MOD = 1000000009;
const int maxn=100011;
const double eps=1e-9;
LL fact[maxn];
LL inv[maxn];
LL factinv[maxn];
void init()
{
fact[0]=fact[1]=1;
inv[0]=inv[1]=1;
factinv[0]=factinv[1]=1;
for(int i=2;i<maxn;++i)
{
fact[i]=fact[i-1]*i%MOD;
inv[i]=(MOD-MOD/i)*inv[MOD%i]%MOD;
factinv[i]=factinv[i-1]*inv[i]%MOD;
}
}
int C(int m,int k)
{
return (fact[m]*factinv[k]%MOD)*factinv[m-k]%MOD;
}
int main()
{
int m,n;
int l,r;
int x;
init();
LL ans;
int oe;
while (cin>>n>>m)
{
ans=0;
int tl,tr;
oe=0;
l=0;r=1;
while(n--){
scan(x);
tl=min(abs(l-x),abs(r-x));
if(l<=x && x<=r) tl=0;
tr=max(m-abs(l+x-m),m-abs(r+x-m));
if(l+x<=m && r+x>=m) tr=m;
oe=(oe+x)%2;
l=tl;r=tr;
}
if(l%2!=oe) l++;
for(int i=l;i<=r;i+=2)
ans=(ans+C(m,i))%MOD;
cout<<ans<<endl;
}
}