HDU 4869 Turn the pokers (2014 多校联合第一场 I)
HDOJ--4869--Turn the pokers【组合数学+快速幂】
题意:有m张扑克,开始时全部正面朝下,你可以翻n次牌,每次可以翻xi张,翻拍规则就是正面朝下变背面朝下,反之亦然,问经过n次翻牌后牌的朝向有多少种情况。我们可以把正面朝上理解为1,反面朝上理解为0,那么可以理解为求01串的不同的组合方式有几种。
解题思路:我们可以知道,每张牌假设起始状态都为0,如果翻奇数次,该牌最后的情况是1,如果翻偶数次,该牌的最后情况为0.根据n次翻牌的个数找出1的个数的下限和上限,然后再在这个范围里用组合数学求有几种排列即可。
我们先来看怎么求1的个数的上限和下限:
Minm:下限 maxm:上限 p:当前的下限 q:当前的上限
1.求1的个数的下限:
当前下限大于等于现在翻牌的数量,这个比较好理解,全翻1,1变成0,则剩下的1就是minm-x;
当前下限小于翻牌数量,上限大于等于翻牌数量,即翻牌数量刚好在上下限之间,所以最少可以把正面朝上的数量减为零,但不一定能减到0,因为有可能当前正面朝上的牌时奇数,而翻牌数量是偶数,所以要判断奇偶性是否一样,为什么要和minm比较奇偶性。如果奇偶性相同,可以减为0,
否则,应该为1。
翻牌数量比上限还大的时候,直接减去上限就是下限。
2.求1的个数的上限:
上限+翻牌数量没有达到总牌数时,上限+翻牌数量就是新的上限,全翻0,这样使1最多;
上限+翻牌数量大于总牌数,而下限+翻牌数量小于等于总牌数,前者可以说是翻牌溢出了,已经全是1再翻的话只会让一些1变成0,后者没有达到全变成1的情况。它们是一个上限一个下限,这说明可以处理到在这之间的情况,那么最好的结果是所有牌都正面朝上,全是1,需要判断奇偶性是否一致,这回和m比较。
上限+翻牌数、下限+翻牌数全都大于总牌数时,说明都会溢出,那就用2 * m - (x + minm)来表示上限,因为(x+minm)小,所以溢出的1变成0的牌数少。
接下来要处理的是计算出 c ( m , i ) 的值:
由于数比较大,要对1000000009取余,这里要用到快速幂取余:
模板如下:
- long long PowerMod (int a, int b, int c)
- {
- int ans = 1;
- a = a % c;
- while(b>0) {
- if(b % 2 = = 1)
- ans = (ans * a) % c;
- b = b/2; // b>>=1;
- a = (a * a) % c;
- }
- return ans;
- }
关于快速幂取余,可以查看链接:http://blog.csdn.net/acm_code/article/details/38270829
用数组c表示组合数学 c ( m , i ) 的值, 按理说 c[ i ] = c[ i - 1 ] * ( m - i + 1 ) / i ,然后这个数对MOD取模,但是存在除法取模就不是这么简单的分解了,费马小定理是这样: a^(p-1) ≡1(mod p),p为质数,a、p互质,a^(p-1) mod p 恒等于1。
变换一下,两边同时除以a ,变成 a^(p-2)=a^(-1)(mod p),所以要除以a 就可以表示成 乘 a^(p-2),所以有了这样的写法:c[i] = c[i-1] * (m-i+1) % MOD * PowerMod(i,MOD-2) % MOD;
最后将组合数学值相加的时候,要隔一个相加,不难发现上限和下限的奇偶性一样。
总和一下上述思想,我们可以写出代码:
#include<stdio.h>
#define MOD 1000000009
__int64 c[];
__int64 mode(__int64 a,int n)
{
__int64 t = a;
__int64 ans = ;
while(n)
{
if(n & )
{
ans = ans * t % MOD;
}
n >>= ;
t = t * t % MOD;
}
return ans;
}
int main()
{
int minm,maxm,x;
int p,q;
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
//初始状态下1的上限和下限都为0;
minm = maxm = ;//maxm表示上限,minm表示下限
p = q = ;//p、q分别记录当前下,上限,然后更新到minm、maxm中
for(int i=; i<n; i++)
{
scanf("%d",&x);//第i次翻牌的数量
//判断下限
if(minm>=x)//当前下限大于等于现在翻牌的数量
p = minm - x;//全翻1,1变成0,则剩下的1就是minm-x else if(maxm>=x)//当前下限小于翻牌数量,上限大于等于翻牌数量,
p = ((x&)==(minm&))?:; //x与minm同奇偶就为0 ,否则为1 else//翻牌数量比上限还大的时候,直接减去上限就是下限
p = x - maxm; //判断上限
if(maxm+x<=m)//上限+翻牌数量没有达到总牌数时,上限+翻牌数量就是新的上限
q = maxm + x; else if(minm+x<=m) //上限+翻牌数量大于总牌数,而下限+翻牌数量小于等于总牌数
q = (((minm+x)&)==(m&))?m:m-;//x与minm同奇偶就为0,否则为1 else//上限+翻牌数、下限+翻牌数全都大于总牌数
q = * m - (x + minm); minm = p;
maxm = q;
}
__int64 sum=;
c[]=;
for(int i=; i<=maxm; i++)//求C(m,i);
{
if(m-i<i)
c[i] = c[m-i];
else
{
c[i] = c[i-]*(m-i+)%MOD*mode((__int64)i,MOD-)%MOD;
}
}
for(int i=minm; i<=maxm; i+=)
{
sum+=c[i];
sum%=MOD;
}
printf("%I64d\n",sum);
}
return ;
}
HDU 4869 Turn the pokers (2014 多校联合第一场 I)的更多相关文章
- HDU 4869 Turn the pokers (2014多校联合训练第一场1009) 解题报告(维护区间 + 组合数)
Turn the pokers Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- HDU 4865 Peter's Hobby(2014 多校联合第一场 E)(概率dp)
题意:已知昨天天气与今天天气状况的概率关系(wePro),和今天天气状态和叶子湿度的概率关系(lePro)第一天为sunny 概率为 0.63,cloudy 概率 0.17,rainny 概率 0.2 ...
- hdu 4869 Turn the pokers (2014多校联合第一场 I)
Turn the pokers Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- HDU 4869 Turn the pokers (2014 Multi-University Training Contest 1)
Turn the pokers Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)T ...
- hdu 4865 Peter's Hobby(2014 多校联合第一场 E)
Peter's Hobby Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) To ...
- HDU 4870 Rating (2014 多校联合第一场 J)(概率)
题意: 一个人有两个TC的账号,一开始两个账号rating都是0,然后每次它会选择里面rating较小的一个账号去打比赛,每次比赛有p的概率+1分,有1-p的概率-2分,当然如果本身是<=2分的 ...
- HDU 4868 Information Extraction(2014 多校联合第一场 H)
看到这道题时我的内心是奔溃的,没有了解过HTML,只能靠窝的渣渣英语一点一点翻译啊TT. Information Extraction 题意:(纯手工翻译,有些用词可能在html中不是一样的,还多包涵 ...
- HDU 4869 Turn the pokers(推理)
HDU 4869 Turn the pokers 题目链接 题意:给定n个翻转扑克方式,每次方式相应能够选择当中xi张进行翻转.一共同拥有m张牌.问最后翻转之后的情况数 思路:对于每一些翻转,假设能确 ...
- hdu 5288||2015多校联合第一场1001题
pid=5288">http://acm.hdu.edu.cn/showproblem.php?pid=5288 Problem Description OO has got a ar ...
随机推荐
- 我的Python成长之路---GitHub使用克隆GitHub(SSH key配置)
六.克隆GitHub仓库 1.创建仓库目录,目录位置没有要求,比如D:\learngit. 2.配置ssh(如果不配置会每次都输入用户名和密码) 使用TortoiseGit生成ssh-key:开始菜单 ...
- iOS8模拟器键盘弹不出来
command + k 或 command + shift + k 切换到模拟器键盘 其默认是Mac键盘
- 用4bit的counter看同步复位与异步复位
先看看这个同步复位 //date: 2013/8/20 //designer :pengxiaoen module counter_4 ( clock,reset, out ); input rese ...
- C#注册表
C#注册表情缘 记得当时刚接触C#的时候,喜欢编写各种小软件,而注册表系列和网络系列被当时的我认为大牛的必备技能.直到我研究注册表前一天我都感觉他是那么的高深. 今天正好有空,于是就研究了下注册表 ...
- Android 四种启动模式 已看晕
http://blog.csdn.net/zdw890412/article/details/7386314 //有点乱 http://www.cnblogs.com/fanchangfa/arch ...
- docker 学习笔记20:docker守护进程的配置与启动
安装好docker后,需要启动docker守护进程.有多种启动方式. 一.服务的方式 因为docker守护进程被安装成服务.所以,可以通过服务的方式启停docker守护进程,包括查看状态. sudo ...
- stm32之ADC
将模拟量转换为数字量的过程称为模式(A/D)转换,完成这一转换的期间成为模数转换器(简称ADC);将数字量转换为模拟量的过程为数模(D/A)转换,完成这一转换的器件称为数模转换器(简称DAC). 模拟 ...
- 如何创建C++程序
下载Microsoft Visual C++ 6.0请点击这里:VC 6.0下载(包括中文版英文版)(支持Win7和XP) 首先,我们要进入Microsoft Visual C++集成开发环境(Int ...
- Oracle多实例的配置方法
SID_LIST_LISTENER = (SID_LIST = (SID_DESC = (SID_NAME = PLSExtProc) (ORACLE_HOME /dbhome_2) (PROGRAM ...
- cocos2d-x的经历(含源码——)
源于手游的火爆和大环境的影响,最近在学习cocos2d-x.其实以前一直有想搞andriod和ios的尝试,可惜本屌丝没钱买mac os x,只好先开始学习andriod,于是买了小米2s作为测试机, ...