Rating ,hdu4870(高校联赛第一场)

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).

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 3
Hint
For 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;
	}
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值