Problem

loj2023

题意概述:甲抛掷 \(a\) 次硬币,乙抛掷 \(b\) 次硬币,问有多少种情况甲正面向上的次数比乙多,答案对 \(10^k\) 取模

对于 \(10\%\) 的数据,\(a,b\le 20\);

对于 \(30\%\) 的数据,\(a,b\le 100\);

对于 \(70\%\) 的数据,\(a,b\le 100000\),其中有 \(20\%\) 的数据满足 \(a=b\);

对于 \(100\%\) 的数据,\(1\le a,b\le {10}^{15}, b\le a\le b+10000, 1\le k\le 9\),数据组数小于等于 \(10\)

10分

枚举俩人的抛掷方式,存下来合并后统计(没有存在的意义) \(O(2^a+2^b+ab)\)

30分

\(\sum_{i=1}^a\binom ai\sum_{j=0}^{\min(b,i-1)}\binom bj\),组合数需预处理 \(O(ab)\)

+20分

由于整个游戏是绝对公平的,即甲赢的概率与乙相当,考虑所有情况减去平局再除以\(2\),得到 \(\frac {2^{a+b}-\sum_{i=0}^a\binom ai^2}2=\frac {2^{a+b}-\binom {2a}a}2\)

70分

考虑预处理 \(f(i)=\sum_{j=0}^{\min(b,i-1)}\binom bj\),再枚举 \(i\) 求和 \(O(a+b)\)

(+20分与70分部分由于模数非质数则需crt或将阶乘拆解成\(k\cdot 2^x\cdot 5^y\)的形式进行模拟除法)

100分

+20做法可扩展,只需再加上甲赢且对称局面乙赢不了的情况再整体除以\(2\)即可,关键在于求新加的这个东西

设甲抛掷 \(a\) 次,得 \(x\) 次正面;乙抛掷 \(b\) 次,得 \(y\) 次正面

则当前情况甲赢,且对称情况乙赢不了(对称情况可以是平局)可以列出式子

\[\begin{cases}
x>y\\
a-x\geq b-y
\end{cases}
\]

已知 \(a,b\),解出 \(0<x-y\leq a-b\),则这一部分的答案已经可以表示为

\[\sum_{y=0}^b\sum_{x=y+1}^{y+(a-b)}\binom ax\binom by
\]

由于 \(a,b\) 都很大,但 \(a-b\leq 10^4\),从此入手,将其提出来

\[\sum_{t=1}^{a-b}\sum_{y=0}^b\binom a{y+t}\binom by
\]

考虑之前+20的做法中\(\sum\binom ai^2=\sum\binom ai\binom a{a-i}=\binom {2a}a\),这里后面\(\sum \binom a{y+t}\binom by=\sum \binom a{y+t}\binom b{b-y}=\binom {a+b}{(y+t)+(b-y)}=\binom {a+b}{b+t}\)

则后面答案为 \(\sum_{t=1}^{a-b}\binom {a+b}{b+t}\)

则整体答案为

\[\frac {2^{a+b}-\binom {2a}a+\sum_{t=1}^{a-b}\binom{a+b}{b+t}}2
\]

由于需要模合数,需要使用\(\mathsf {exLucas}\)解决……

至于如何除以 \(2\),可以将模数翻倍,最后直接除以 \(2\)

然后就TLE爆零了 分数不如暴力70,除此之外,还需要注意一些卡常技巧(从\(60s+\)到\(3s\)的华丽蜕变)

模数优化

由于模数只能是\(10^k\),所以可以考虑只模\(10^9\),最后再模\(10^k\),可以保证模数唯一,从而预处理模数的质因子分解

模数的质因子只有 \(2\) 和 \(5\),可以储存下来,对应的 \(p^k\) 分别为 \(2^{10},5^9\)

(到这里能拿 \(30\) 分啦)

调用优化

(优化效果特明显)

将两个模数开两个namespace,每个namespace内部由于模数相等,不需要传递模数

(到这里能拿 \(70\) 分啦)

组合数

由于 \(\binom nm = \binom n{n-m}\)

而得到的式子 \(\sum_{t=1}^{a-b}\binom{a+b}{b+t}\) 中以 \(\frac {a+b}2\) 为中心轴,两侧组合数对称,只要算一半即可(中间值特判一下)

Fac优化

由于每次询问的组合数下标都是 \(a+b\),所以可以在每组数据中预处理出 \(Fac(a+b)\),就不用每次重新调用了

预处理

\(p^k\)以内除去\(p\)的阶乘 是可以预处理的,同样 \(p^k\) 也是可以预处理的

至于是否要预处理所有 除去 \(p\) 的阶乘,由于询问次数较少,预处理耗时不比直接询问快

(到这里能拿 \(100\) 分啦)

玄学优化

(优化效果最明显)

若在函数 C(ll n,ll m,ll pi,ll pk)中,算出的 \(k\) 若比 \(pk\) 的幂次大,则直接返回 0ll

HN的题真毒,考场上遇到这题还是不要写正解,写了也被卡常

Code

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. const int p = 2e9;
  5. const int pw2 = 1024;
  6. const int pw5 = 1953125;
  7. int fac[2][pw5+2];
  8. int Pw [2][pw5+2];
  9. void exgcd(ll a,ll b,ll&x,ll&y){
  10. if(!b){x = 1, y = 0; return ;}
  11. exgcd(b,a%b,y,x); y -= a/b*x;
  12. }
  13. inline ll inv(ll n,ll mod){
  14. ll x,y; exgcd(n,mod,x,y);
  15. return (x+mod)%mod;
  16. }
  17. namespace Lucas2{
  18. const int pi = 2;
  19. const int pk = pw2;
  20. ll k_n;int Fac_n;
  21. inline ll inv(ll n){ll x,y; exgcd(n,pk,x,y);return (x+pk)%pk;}
  22. inline ll qpow(ll A,ll B){ll res(1ll);while(B){if(B&1)res=res*A%pk;A=A*A%pk,B>>=1;}return res;}
  23. ll Fac(ll n){
  24. if(!n) return 1ll;
  25. ll res = 1ll;
  26. res = fac[0][pk];
  27. res = qpow(res,n/pk);
  28. res = res * fac[0][n%pk]%pk;
  29. return res * Fac(n/pi)%pk;
  30. }
  31. inline ll C(ll n,ll m){
  32. ll k = k_n;
  33. for(ll i = m; i; i/=pi) k -= i/pi;
  34. for(ll i=n-m; i; i/=pi) k -= i/pi;
  35. if(k>=10) return 0ll;
  36. ll d0 = Fac_n;
  37. ll d1 = Fac(m);
  38. ll d2 = Fac(n-m);
  39. return d0 * inv(d1)%p * inv(d2)%p * Pw[0][k]%pk;
  40. }
  41. inline ll CRT(ll b){return b * inv(p/pk)%p * (p/pk)%p;}
  42. inline void pre(ll n){
  43. Fac_n = Fac(n),k_n = 0ll;
  44. for(ll i = n; i; i/=pi)k_n += i/pi;
  45. }
  46. }
  47. namespace Lucas5{
  48. const int pi = 5;
  49. const int pk = pw5;
  50. ll k_n;int Fac_n;
  51. inline ll inv(ll n){ll x,y; exgcd(n,pk,x,y);return (x+pk)%pk;}
  52. inline ll qpow(ll A,ll B){ll res(1ll);while(B){if(B&1)res=res*A%pk;A=A*A%pk,B>>=1;}return res;}
  53. ll Fac(ll n){
  54. if(!n) return 1ll;
  55. ll res = 1ll;
  56. res = fac[1][pk];
  57. res = qpow(res,n/pk);
  58. res = res * fac[1][n%pk]%pk;
  59. return res * Fac(n/pi)%pk;
  60. }
  61. inline ll C(ll n,ll m){
  62. ll k = k_n;
  63. for(ll i = m; i; i/=pi) k -= i/pi;
  64. for(ll i=n-m; i; i/=pi) k -= i/pi;
  65. if(k>=9) return 0ll;
  66. ll d0 = Fac_n;
  67. ll d1 = Fac(m);
  68. ll d2 = Fac(n-m);
  69. return d0 * inv(d1)%p * inv(d2)%p * Pw[1][k]%pk;
  70. }
  71. inline ll CRT(ll b){return b * inv(p/pk)%p * (p/pk)%p;}
  72. inline void pre(ll n){
  73. Fac_n = Fac(n),k_n = 0ll;
  74. for(ll i = n; i; i/=pi)k_n += i/pi;
  75. }
  76. }
  77. ll exLucas(ll n,ll m){
  78. ll res = 0ll;
  79. res += Lucas2::CRT(Lucas2::C(n,m));
  80. res += Lucas5::CRT(Lucas5::C(n,m));
  81. return res%p;
  82. }
  83. char ss[10];
  84. void print(int x,int pp){
  85. x%=(int)pow(10,pp);
  86. ss[0] = '%', ss[1] = '0';
  87. sprintf(ss+2,"%dd\n",pp);
  88. printf(ss,x);
  89. }
  90. void prework(int a,int b){
  91. int*arr=fac[a==5];
  92. int*trr= Pw[a==5];
  93. arr[0]=trr[0]=1;
  94. for(int i=1;i<=b;++i){
  95. trr[i] = (ll)trr[i-1]*a%b;
  96. arr[i] = arr[i-1];
  97. if(i%a)arr[i]=(ll)arr[i]*i%b;
  98. }
  99. }
  100. inline ll qpow(ll A,ll B){
  101. ll res(1ll);while(B){
  102. if(B&1) res = res*A%p;
  103. A = A*A%p, B>>=1;
  104. }return res;
  105. }
  106. int main(){
  107. ll a,b;int pp;
  108. prework(2,pw2);
  109. prework(5,pw5);
  110. while(~scanf("%lld%lld%d",&a,&b,&pp)){
  111. ll res = qpow(2,a+b);
  112. Lucas2::pre(a+b);
  113. Lucas5::pre(a+b);
  114. // res = (res - exLucas(a+b,a)+p)%p;
  115. // for(int i=1;i<=a-b;++i) res = (res + exLucas(a+b,b+i))%p;
  116. if(a == b){
  117. res = (res - exLucas(a+b,a)+p)%p;
  118. print(res>>1,pp); continue;
  119. }
  120. for(ll i=(a+b-1>>1);i!=b;--i)
  121. res = (res + 2ll*exLucas(a+b,i))%p;
  122. if(0 == ((a+b)&1))
  123. res = (res + exLucas(a+b,a+b>>1))%p;
  124. print(res>>1,pp);
  125. }
  126. return 0;
  127. }

题解-HNOI2017 抛硬币的更多相关文章

  1. 【BZOJ4830】[HNOI2017]抛硬币(组合计数,拓展卢卡斯定理)

    [BZOJ4830][HNOI2017]抛硬币(组合计数,拓展卢卡斯定理) 题面 BZOJ 洛谷 题解 暴力是啥? 枚举\(A\)的次数和\(B\)的次数,然后直接组合数算就好了:\(\display ...

  2. bzoj 4830: [Hnoi2017]抛硬币 [范德蒙德卷积 扩展lucas]

    4830: [Hnoi2017]抛硬币 题意:A投a次硬币,B投b次硬币,a比b正面朝上次数多的方案数,模\(10^k\). \(b \le a \le b+10000 \le 10^{15}, k ...

  3. bzoj4830 hnoi2017 抛硬币

    题目描述 小 A 和小 B 是一对好朋友,他们经常一起愉快的玩耍.最近小 B 沉迷于**师手游,天天刷本,根本无心搞学习.但是已经入坑了几个月,却一次都没有抽到 SSR,让他非常怀疑人生.勤勉的小 A ...

  4. luogu P3726 [AH2017/HNOI2017]抛硬币

    传送门 我是真的弱,看题解都写了半天,,, 这题答案应该是\(\sum_{i=1}^{a}\binom{a}{i}\sum_{j=0}^{min(b,i-1)}\binom{b}{j}\) 上面那个式 ...

  5. [luogu3726 HNOI2017] 抛硬币 (拓展lucas)

    传送门 数学真的太优秀了Orz 数据真的太优秀了Orz 题目描述 小 A 和小 B 是一对好朋友,他们经常一起愉快的玩耍.最近小 B 沉迷于**师手游,天天刷本,根本无心搞学习.但是已经入坑了几个月, ...

  6. bzoj 4830: [Hnoi2017]抛硬币

    Description 小A和小B是一对好朋友,他们经常一起愉快的玩耍.最近小B沉迷于**师手游,天天刷本,根本无心搞学习.但是 已经入坑了几个月,却一次都没有抽到SSR,让他非常怀疑人生.勤勉的小A ...

  7. [AH/HNOI2017]抛硬币

    题目描述 小 A 和小 B 是一对好朋友,他们经常一起愉快的玩耍.最近小 B 沉迷于**师手游,天天刷本,根本无心搞学习.但是已经入坑了几个月,却一次都没有抽到 SSR,让他非常怀疑人生.勤勉的小 A ...

  8. 【刷题】BZOJ 4830 [Hnoi2017]抛硬币

    Description 小A和小B是一对好朋友,他们经常一起愉快的玩耍.最近小B沉迷于**师手游,天天刷本,根本无心搞学习.但是已经入坑了几个月,却一次都没有抽到SSR,让他非常怀疑人生.勤勉的小A为 ...

  9. [HNOI2017]抛硬币

    Description 小A和小B是一对好朋友,他们经常一起愉快的玩耍.最近小B沉迷于××师手游,天天刷本,根本无心搞学习.但是已经入坑了几个月,却一次都没有抽到SSR,让他非常怀疑人生.勤勉的小A为 ...

随机推荐

  1. FineUIPro/Mvc/Core/JS v4.2.0 发布了(老牌ASP.NET控件库,WebForms,ASP.NET MVC,Core,JavaScript)!

    还记得 10 年前那个稍微青涩的 ExtAspNet 吗,如今她已脱胎换骨,变成了如下 4 款产品: FineUIPro:基于jQuery的经典款ASP.NET WebForms控件,之前的FineU ...

  2. H5网页后在返回到微信公众平台自定义菜单

    <p class="success">订阅成功!</p> <div class="btn" @click="finish ...

  3. 算法笔记-状压dp

    状压dp 就是把状态压缩的dp 这样还是一种暴力但相对于纯暴力还是优雅的多. 实际上dp就是经过优化的暴力罢了 首先要了解位运算 给个链接吧 [https://blog.csdn.net/u01337 ...

  4. Windows 与Office 镜像的区别

    .SW开头是批量授权的版本. .CN开头是简体中文版镜像文件 零售版本. 其实建议使用 SW开头的镜像 可以直接使用KMS进行激活了. 转帖一个百度知道的内容: 看安装包的名称 cn开头的是零售版的, ...

  5. SpringBoot使用Filter过滤器处理是否登录的过滤时,用response.sendRedirect()转发报错

    1.使用response.sendRedirect("/login")时报错,控制台报错如下: Cannot call sendError() after the response ...

  6. Android艺术——深看Activity的生命周期

    探究Activity的生命周期 1.典型情况下的生命周期分析:onCreate 初始化工作,加载布局资源和数据:onStart ac正在启动但是无法交互,后台:onResume ac可见,显示在前台: ...

  7. 其它综合-企业级CentOS 7.6 操作系统的安装

    企业级CentOS 7.6版本安装过程 1. 环境: 使用的虚拟机软件是VMware,版本为 12 .(网上一搜一大推,在此不再演示.) 使用的ISO镜像为CentOS7.6.(自己也可以在网上搜镜像 ...

  8. python常用的基本操作

    打开cmd,pip list 可以查看python安装的所以第三方包

  9. rest framework 解析器,渲染器

    解析器 解析器的作用 解析器的作用就是服务端接收客户端传过来的数据,把数据解析成自己可以处理的数据.本质就是对请求体中的数据进行解析. 请求体相关字段: Accept:指定了接收的数据类型 Conte ...

  10. hdu5238 calculator (线段树+crt)

    (并不能)发现29393不是质数,而是等于7*13*17*19 于是可以用四个线段树分别维护模意义下,对x进行一个区间的操作后的值 最后再把这四个的答案用crt拼起来 也可以不crt,而是预处理0~2 ...