链接:http://acm.hdu.edu.cn/showproblem.php?pid=4869

题意:有m张扑克。開始时所有正面朝下。你能够翻n次牌,每次能够翻xi张。翻拍规则就是正面朝下变背面朝下,反之亦然,问经过n次翻牌后牌的朝向有多少种情况。

这道题在比赛时我们仅仅开了个头。却无从下手。

我看了网上的解题报告。说的都比較简单,对于我这名菜鸟来说也想了比較长的时间才想明确,所以我想写的清晰一些日后再看还能看的非常清晰。

思路是这样,每张牌翻奇数次必定是正面朝上。翻偶数次则还是正面朝下。如今用0表示初始状态(正面朝下),1表示正面朝上,能够依据n次翻牌的个数找出1的下限和上限。然后再在这个范围里用组合数学就ok了。比赛时就是想到了这里,找范围没有想出来。

这道题能够分为两部分:先是找到1的上限和下限,然后是计算出 c ( m , i ) 的值依次相加。

第一部分:

        minm = maxm = 0;
p = q = 0;
for(i=0;i<n;i++){
scanf("%d",&x);
if(minm>=x) p = minm - x; //一
else if(maxm>=x) p = ((x&1)==(minm&1))?0:1; //二
else p = x - maxm; //三
if(maxm+x<=m) q = maxm + x; //四
else if(minm+x<=m) q = (((minm+x)&1)==(m&1))? m:m-1; //五
else q = 2 * m - (x + minm); //六
minm = p;
maxm = q;
}

minm表示下限,maxm表示上限,p、q分别记录当前上下限,然后更新到minm、maxm中。x是输入的第i次翻牌的数量

第一组if语句是推断下限的。

①:当前下限大于等于如今翻牌的数量,这个比較好理解。全翻1,1变成0,则剩下的1就是minm-x

②:当前下限小于翻牌数量。上限大于等于翻牌数量。由于翻牌数量刚好在上下限之间,所以最少能够把正面朝上的数量减为零,但不是绝对能减到0,由于有可能当前正面朝上的牌时奇数。而翻牌数量是偶数,所以要推断奇偶性是否一样。为什么要和minm比較奇偶性。后面会说。

③:翻牌数量比上限还大的时候,直接减去上限就是下限。也不难理解

④:上限+翻牌数量没有达到总牌数时,上限+翻牌数量就是新的上限。全翻0,这样使1最多

⑤:上限+翻牌数量大于总牌数,而下限+翻牌数量小于等于总牌数,前者能够说是翻牌溢出了,已经全是1再翻的话仅仅会让一些1变成0,后者没有达到全变成1的情况。

它们是一个上限一个下限。这说明能够处理到在这之间的情况,那么最好的结果是全部牌都正面朝上,全是1。和②的情况一样。须要推断奇偶性是否一致。这回和m比較。应该比②的好理解

⑥:上限+翻牌数、下限+翻牌数全都大于总牌数时。说明都会溢出,那就用2 * m - (x + minm)来表示上限。由于(x+minm)小。所以溢出的1变成0的牌数少。我之前用max(maxm + x - m, 2 * m - (x + minm))来表示⑥的上限,结果WA了。事实上是我想错了,maxm + x - m是1变成0的牌的数量。而要找的是1的上限。

第二部分:

        c[0] = 1;
for(i=1;i<=maxm;i++){
if(m-i<i) c[i] = c[m-i];
else{
c[i] = c[i-1] * (m-i+1) % MOD * mode((ll)i,MOD-2) % MOD;
}
}

当中mode是高速幂取模函数,数组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)。所以有了如上的写法。

最后将组合数学值相加的时候。要隔一个相加,不难发现上限和下限的奇偶性一样,而且每种结果1的数量的奇偶性一定和上限下限的奇偶性一样,这个能够自己推

我以列的方式表示牌的情况,O表示翻哪个牌,如果如今有7张牌。翻两次。第一次翻4张,第二次翻三张

不论你怎么变化。每次翻完牌正面朝上的总是奇数个或偶数个,其它情况能够自己推,得到这个结论。

如今说说第一部分的②,事实上应该和你如今更接近的那种情况去比較奇偶性,可是相比于某种中间情况,上下限的奇偶性更easy推断,并且中间每种情况的奇偶性都和上下限一样。所以能够x能够和minm比較奇偶性。当然。和maxm比較也能够,由于他们奇偶性一样。

完整代码:

#include<cstring>
#include<string>
#include<fstream>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cctype>
#include<algorithm>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<stack>
#include<ctime>
#include<cstdlib>
#include<functional>
#include<cmath>
using namespace std;
#define PI acos(-1.0)
#define MAXN 100100
#define eps 1e-7
#define MOD 1000000009
#define INF 0x7FFFFFFF
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef long long ll; ll c[MAXN];
ll mode(ll a,int n){
ll t = a;
ll ans = 1;
while(n){
if(n & 1){
ans = ans * t % MOD;
}
n >>= 1;
t = t * t % MOD;
}
return ans;
}
int main(){
int n,m,minm,maxm,i,j,x,p,q;
while(scanf("%d%d",&n,&m)!=EOF){
minm = maxm = 0;
p = q = 0;
for(i=0;i<n;i++){
scanf("%d",&x);
if(minm>=x) p = minm - x;
else if(maxm>=x) p = ((x&1)==(minm&1))?0:1;
else p = x - maxm;
if(maxm+x<=m) q = maxm + x;
else if(minm+x<=m) q = (((minm+x)&1)==(m&1))? m:m-1;
else q = 2 * m - (x + minm);
minm = p;
maxm = q;
}
ll ans = 0LL;
c[0] = 1;
for(i=1;i<=maxm;i++){
if(m-i<i) c[i] = c[m-i];
else{
c[i] = c[i-1] * (m-i+1) % MOD * mode((ll)i,MOD-2) % MOD;
}
}
for(i=minm;i<=maxm;i+=2){
ans += c[i];
ans %= MOD;
}
cout<<ans<<endl;
}
return 0;
}

HDOJ--4869--Turn the pokers【组合数学+高速幂】的更多相关文章

  1. HDOJ 4869 Turn the pokers

    最后的结果中正面向上的奇偶性是一定的,计算出正面向上的范围low,up 结果即为 C(m.low)+ C(m.low+2) +.... + C(m,up) ,用逆元取模 Turn the pokers ...

  2. HDU 4869 Turn the pokers(推理)

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

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

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

  4. hdu 4869 Turn the pokers (思维)

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

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

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

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

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

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

  8. HDOJ 4686 Arc of Dream 矩阵高速幂

    矩阵高速幂: 依据关系够建矩阵 , 高速幂解决. Arc of Dream Time Limit: 2000/2000 MS (Java/Others)    Memory Limit: 65535/ ...

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

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

随机推荐

  1. UIPageControll - 图片格式

    设置pageCon的显示风格: 1. 颜色 page.pageIndicatorTintColor = [UIColor redColor]; page.currentPageIndicatorTin ...

  2. 可以用来开发h5的软件小结

    webStorm phoneGap notepad++ eclips text sublime dreamWeaver intellij idea 学习h5 需要掌握的  大块的知识 xhtml ja ...

  3. XE5 开发android平台搭建

    转载自:http://www.cnblogs.com/hezihang/p/3319980.html Delphi XE5的Android开发平台搭建   Delphi XE5支持Android AR ...

  4. csu 10月 月赛 J 题

    Description CSU又到了一年中评奖学金的时候了……各大学霸都或多或少地拿到了各种奖学金(你们自己看着办吧). 在这里,评奖学金有个很奇怪的规矩——每个同学得到的奖学金数一定满足相邻的两个非 ...

  5. 【Hihocoder 1167】 高等理论计算机科学 (树链的交,线段树或树状数组维护区间和)

    [题意] 时间限制:20000ms 单点时限:1000ms 内存限制:256MB 描述 少女幽香这几天正在学习高等理论计算机科学,然而她什么也没有学会,非常痛苦.所以她出去晃了一晃,做起了一些没什么意 ...

  6. 基于Delphi的Socket I/O模型全接触 good

    老陈有一个在外地工作的女儿,不能经常回来,老陈和她通过信件联系.他们的信会被邮递员投递到他们的信箱里. 这和Socket模型非常类似.下面我就以老陈接收信件为例讲解Socket I/O模型. 一:se ...

  7. Android ListView内容变化后的动态刷新

    ListView内容变化后的动态刷新 基本知识点: 1.更新适配器Adapter数据源 2.调用适配器Adapter的刷新方法notifyDataSetChanged() 首先需要定义ListView ...

  8. 透过表象看本质!?之二——除了最小p乘,还有PCA

    如图1所示,最小p乘法求得是,而真实值到拟合曲线的距离为.那么,对应的是什么样的数据分析呢? 图1 最小p乘法的使用的误差是.真实值到拟合曲线的距离为 假如存在拟合曲线,设直线方程为.真实值到该曲线的 ...

  9. POJ_3045_Cow_Acrobats_(贪心)

    描述 http://poj.org/problem?id=3045 n头牛,每头牛都有重量w[i]和力量s[i].把这n头牛落起来,每头牛会有一个危险值,危险值是它上面所有牛的重量和减去它的力量.求危 ...

  10. [转]ESCAPE()、ENCODEURI()、ENCODEURICOMPONENT()区别详解

    escape().encodeURI().encodeURIComponent()区别详解 JavaScript中有三个可以对字符串编码的函数,分别是: escape,encodeURI,encode ...