Turn the pokers

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1064    Accepted Submission(s): 398

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)

 

果然又是一道神题目,用到的知识点真心多且有用。
 
快速幂+费马小定理+巧妙的思路
 
费马小定理:假如p是质数,且(a,p)=1,那么 a^(p-1) ≡1(mod p)因此 a * a^(p-2)  ≡1(mod p),即 a的乘法逆元是a^(p-2)
因此题目需要求组合数:( n!/m!(n-m)! ) mod p =[ n! mod p ]*[ (m! mod p)^(p-2) mod p]*[ ((n-m)! mod p)^(p-2) mod p] mod p
 
多搞几个数据,可以发现,只需找到最少翻动牌个数与最多翻动牌个数即可,中间的状态是连续的,剩下就是排列的问题了。
因为每次翻一张牌,则正面增加1,反面减1,因此翻动的牌数是偶数变化的,又翻的牌可以随机,所以其最多与最少翻动牌数中间每隔一个都是允许出现的情况。
 
官方题解:

最终的结果一定是连续出现的,只需要求出最终的区间。

因为如果对同一张牌进行两次操作,牌的状态不改变。故牌的翻转次数一定是减少偶数次。如果所有数的和是奇数,那么最终结果也一定是奇数。同理,偶数也是一样的。

所以只要递推求出最后的区间,计算sum(C(xi,m)(i=0,1,2。。。)),m是总牌数,xi是在区间内连续的奇数或偶数,在模10^9+9就是最终的答案。

#include <cstdio>
#include <iostream>
#include <cmath>
#define Mod 1000000009
#define max(x,y) ((x)>(y)?x:y)
#define min(x,y) ((x)<(y)?x:y)
using namespace std;
long long J[];
int n,m,a[],l,r,nl,nr;
void Predo(){
J[]=;
for(int i=;i<=;i++)
J[i]=(J[i-]*i)%Mod;
}
long long Q(long long a,long long p){
int e[],k=;
while(p){
e[k++]=p%;
p=p/;
}
long long tmp=;
for(int i=k-;i>=;i--)
if(e[i]) tmp=((tmp*tmp)%Mod*a)%Mod;
else tmp=(tmp*tmp)%Mod;
return tmp;
}
long long C(int n,int m){
return ((J[n]*Q(J[m],Mod-))%Mod*Q(J[n-m],Mod-))%Mod;
}
int main()
{
Predo();
while(scanf("%d%d",&n,&m)!=EOF){
for(int i=;i<n;i++){
scanf("%d",&a[i]);
}
int l=r=a[];
for(int i=;i<n;i++){
nl=min(abs(l-a[i]),abs(r-a[i]));
if(l<=a[i]&&a[i]<=r){
if((a[i]-l)%==) nl=;
else nl=;
}
nr=max(l+a[i]<=m?l+a[i]:*m-l-a[i] , r+a[i]<=m?r+a[i]:*m-r-a[i]);
if(m-r<=a[i]&&a[i]<=m-l){
if((a[i]-(m-r))%==) nr=m;
else nr=m-;
}
l=nl;
r=nr;
}
long long ans=;
for(int i=l;i<=r;i=i+)
ans=(ans+C(m,i))%Mod;
printf("%lld\n",ans);
}
return ;
}

HDU 4869 Turn the pokers (2014 Multi-University Training Contest 1)的更多相关文章

  1. HDU 4869 Turn the pokers (2014多校联合训练第一场1009) 解题报告(维护区间 + 组合数)

    Turn the pokers Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  2. HDU 4869 Turn the pokers (2014 多校联合第一场 I)

    HDOJ--4869--Turn the pokers[组合数学+快速幂] 题意:有m张扑克,开始时全部正面朝下,你可以翻n次牌,每次可以翻xi张,翻拍规则就是正面朝下变背面朝下,反之亦然,问经过n次 ...

  3. HDU 4869 Turn the pokers(推理)

    HDU 4869 Turn the pokers 题目链接 题意:给定n个翻转扑克方式,每次方式相应能够选择当中xi张进行翻转.一共同拥有m张牌.问最后翻转之后的情况数 思路:对于每一些翻转,假设能确 ...

  4. hdu 4869 Turn the pokers (2014多校联合第一场 I)

    Turn the pokers Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  5. hdu 4869 Turn the pokers (思维)

    Turn the pokers Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  6. HDU 4869 Turn the pokers(思维+组合公式+高速幂)

    pid=4869" target="_blank">Turn the pokers 大意:给出n次操作,给出m个扑克.然后给出n个操作的个数a[i],每一个a[i] ...

  7. 2014多校第一场 I 题 || HDU 4869 Turn the pokers(费马小定理+快速幂模)

    题目链接 题意 : m张牌,可以翻n次,每次翻xi张牌,问最后能得到多少种形态. 思路 :0定义为反面,1定义为正面,(一开始都是反), 对于每次翻牌操作,我们定义两个边界lb,rb,代表每次中1最少 ...

  8. hdu 4869 Turn the pokers(组合数+费马小定理)

    Problem Description During summer vacation,Alice stay at home for a long time, with nothing to do. S ...

  9. HDU 4869 Turn the pokers(思维+逆元)

    考试的时候没有做出来... 想到了答案一定是一段连续的区间,一直在纠结BFS判断最后的可行1数. 原来直接模拟一遍就可以算出来最后的端点... 剩下的就是组合数取模了,用逆元就行了... # incl ...

随机推荐

  1. 【转】android 内存泄漏相关收藏博客。

    关于android内存泄漏的研究   博客建了几个月,都没有去写,一是因为当时换工作,然后又是新入职(你懂的,好好表现),比较忙:二是也因为自己没有写博客的习惯了.现在还算是比较稳定了,加上这个迭代基 ...

  2. 【转载】OpenStack Swift学习笔记

    免责声明:     本文转自网络文章,转载此文章仅为个人收藏,分享知识,如有侵权,请联系博主进行删除.     原文作者:崔炳华      原文地址:http://blog.csdn.net/i_ch ...

  3. ExtJS4.2学习(21)动态菜单与表格数据展示操作总结篇2

    运行效果: 此文介绍了根据操作左侧菜单在右面板展示相应内容. 一.主页 先看一下跳转主页的方式:由在webapp根目录下的index.jsp跳转至demo的index.jsp 下面是demo的inde ...

  4. Vim Cscope安装与使用

    问题描述:        Cscope是VIM适用的工具和插件,通过Cscope可以方便的获取某个函数的定义以及被那些函数调用 问题解决:         (1)Cscope安装    注:      ...

  5. 【ZOJ】【3329】One Person Game

    概率DP/数学期望 kuangbin总结题目中的第三道 看来还是没有进入状态啊……都说是DP了……当然是要找[状态之间的转移关系]了…… 本题中dp[i]跟 dp[i-(k1+k2+k3)] 到dp[ ...

  6. LoadAssetAtPath 与 Load 的区别

    一.官方的文档 Resources.LoadAssetAtPath Returns a resource at an asset path (Editor Only). This function a ...

  7. JDK8 学习

    http://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html

  8. Android AlarmManager的取消

    取消alarm使用AlarmManager.cancel()函数,传入参数是个PendingIntent实例. 该函数会将所有跟这个PendingIntent相同的Alarm全部取消,怎么判断两者是否 ...

  9. 学习selenium需要具备的知识或技术

    因为有QTP和JAVA的基础,selenium学起来会快很多,总结下学习selenium所需要具备的知识或技术 1.selenium进行的自动化测试是基于ui层面的,所以html,css,javasc ...

  10. [转]HttpClient的超时用法小记

    HttpClient的超时用法小记 HttpClient在使用中有两个超时时间,是一直接触和使用的,由于上次工作中使用httpClient造成了系统悲剧的情况,特地对它的两个超时时间进行了小小的测试, ...