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取余,这里要用到快速幂取余:

模板如下:

  1. long long  PowerMod (int a, int b, int c)
  2. {
  3. int  ans = 1;
  4. a = a % c;
  5. while(b>0) {
  6. if(b % 2 = = 1)
  7. ans = (ans * a) % c;
  8. b = b/2;       //   b>>=1;
  9. a = (a * a) % c;
  10. }
  11. return ans;
  12. }

关于快速幂取余,可以查看链接: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;

最后将组合数学值相加的时候,要隔一个相加,不难发现上限和下限的奇偶性一样。

总和一下上述思想,我们可以写出代码:

 1 #include<stdio.h>
 2 #define MOD 1000000009
 3 __int64 c[100100];
 4 __int64  mode(__int64 a,int n)
 5 {
 6     __int64 t = a;
 7     __int64 ans = 1;
 8     while(n)
 9     {
10         if(n & 1)
11         {
12             ans = ans * t % MOD;
13         }
14         n >>= 1;
15         t =  t * t % MOD;
16     }
17     return ans;
18 }
19 int main()
20 {
21     int minm,maxm,x;
22     int p,q;
23     int n,m;
24     while(scanf("%d%d",&n,&m)!=EOF)
25     {
26         //初始状态下1的上限和下限都为0;
27         minm = maxm = 0;//maxm表示上限,minm表示下限
28         p = q = 0;//p、q分别记录当前下,上限,然后更新到minm、maxm中
29         for(int i=0; i<n; i++)
30         {
31             scanf("%d",&x);//第i次翻牌的数量
32             //判断下限
33             if(minm>=x)//当前下限大于等于现在翻牌的数量
34                 p = minm - x;//全翻1,1变成0,则剩下的1就是minm-x
35
36             else if(maxm>=x)//当前下限小于翻牌数量,上限大于等于翻牌数量,
37                 p = ((x&1)==(minm&1))?0:1;    //x与minm同奇偶就为0 ,否则为1
38
39             else//翻牌数量比上限还大的时候,直接减去上限就是下限
40                 p = x - maxm;
41
42             //判断上限
43             if(maxm+x<=m)//上限+翻牌数量没有达到总牌数时,上限+翻牌数量就是新的上限
44                 q = maxm + x;
45
46             else if(minm+x<=m) //上限+翻牌数量大于总牌数,而下限+翻牌数量小于等于总牌数
47                 q = (((minm+x)&1)==(m&1))?m:m-1;//x与minm同奇偶就为0,否则为1
48
49             else//上限+翻牌数、下限+翻牌数全都大于总牌数
50                 q = 2 * m - (x + minm);
51
52             minm = p;
53             maxm = q;
54         }
55         __int64 sum=0;
56         c[0]=1;
57         for(int i=1; i<=maxm; i++)//求C(m,i);
58         {
59             if(m-i<i)
60                 c[i] = c[m-i];
61             else
62             {
63                 c[i] = c[i-1]*(m-i+1)%MOD*mode((__int64)i,MOD-2)%MOD;
64             }
65         }
66         for(int i=minm; i<=maxm; i+=2)
67         {
68             sum+=c[i];
69             sum%=MOD;
70         }
71         printf("%I64d\n",sum);
72     }
73     return 0;
74 }
时间: 2024-08-24 13:58:25

HDU 4869 Turn the pokers (2014 多校联合第一场 I)的相关文章

hdu 4865 Peter&#39;s Hobby(2014 多校联合第一场 E)

题意:已知昨天天气与今天天气状况的概率关系(wePro),和今天天气状态和叶子湿度的概率关系(lePro)第一天为sunny 概率为 0.63,cloudy 概率 0.17,rainny 概率 0.2.给定n天的叶子湿度状态,求这n天最可能的天气情况 分析:概率dp设 dp[i][j] 表示第i天天气为j的最大概率,pre[i][j]表示第i天天气最可能为j的前一天天气,dp[i][j]=max(dp[i-1][k]+log(wePro[k][j])+log(lePro[j][lePos[i]]

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

Turn the pokers Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1265    Accepted Submission(s): 465 Problem Description During summer vacation,Alice stay at home for a long time, with nothing t

hdu 4865 Peter&amp;#39;s Hobby(2014 多校联合第一场 E)

Peter's Hobby Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 545    Accepted Submission(s): 237 Problem Description Recently, Peter likes to measure the humidity of leaves. He recorded a leaf

hdu 4865 Peter&#39;s Hobby(2014 多校联合第一场 E)

Peter's Hobby Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 545    Accepted Submission(s): 237 Problem Description Recently, Peter likes to measure the humidity of leaves. He recorded a leaf

2014多校联合第一场

1001:Couple doubi 暴力打表找规律可知,对于任意的p. (1^i+2^i+...+(p-1)^i)%p={ 非0     ,i%(p-1)==0 0        ,  i%(p-1)!=0 } 所以,结果就很显然了. #include <iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<stdlib.h> #include<c

HDU 4870 Rating (2014 多校联合第一场 J)(概率)

题意: 一个人有两个TC的账号,一开始两个账号rating都是0,然后每次它会选择里面rating较小的一个账号去打比赛,每次比赛有p的概率+1分,有1-p的概率-2分,当然如果本身是<=2分的也就还是回到0分.然后问最后其中一个账号到达20分时需要打多少次比赛. 思路: 因为每次50分,到达1000分,所以可以看做每次1分,到达20分dp[i]表示i到20的数学期望那么dp[i] = dp[i+1]*p+dp[i-2]*q+1;令t[i] = dp[i+1]-dp[i]则t[i] = (t[i

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

题目链接 题意 : m张牌,可以翻n次,每次翻xi张牌,问最后能得到多少种形态. 思路 :0定义为反面,1定义为正面,(一开始都是反), 对于每次翻牌操作,我们定义两个边界lb,rb,代表每次中1最少时最少的个数,rb代表1最多时的个数.一张牌翻两次和两张牌翻一次 得到的奇偶性相同,所以结果中lb和最多的rb的奇偶性相同.如果找到了lb和rb,那么,介于这两个数之间且与这两个数奇偶性相同的数均可取到,然后在这个区间内求组合数相加(若lb=3,rb=7,则3,5,7这些情况都能取到,也就是说最后的

HDU 4869 Turn the pokers 多校训练第一场1009

Turn the pokers Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 282    Accepted Submission(s): 89 Problem Description During summer vacation,Alice stay at home for a long time, with nothing to

hdu 4869 Turn the pokers(递推&amp;组合数学&amp;逆元)

Turn the pokers Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1279    Accepted Submission(s): 466 Problem Description During summer vacation,Alice stay at home for a long time, with nothing t