bzoj4830 hnoi2017 抛硬币
题目描述
小 A 和小 B 是一对好朋友,他们经常一起愉快的玩耍。最近小 B 沉迷于**师手游,天天刷本,根本无心搞学习。但是已经入坑了几个月,却一次都没有抽到 SSR,让他非常怀疑人生。勤勉的小 A 为了劝说小 B 早日脱坑,认真学习,决定以抛硬币的形式让小 B 明白他是一个彻彻底底的非洲人,从而对这个游戏绝望。两个人同时抛 b 次硬币,如果小 A 的正面朝上的次数大于小 B 正面朝上的次数,则小 A 获胜。
但事实上,小 A 也曾经沉迷过拉拉游戏,而且他一次 UR 也没有抽到过,所以他对于自己的运气也没有太大把握。所以他决定在小 B 没注意的时候作弊,悄悄地多抛几次硬币,当然,为了不让小 B 怀疑,他不会抛太多次。现在小 A 想问你,在多少种可能的情况下,他能够胜过小 B 呢?由于答案可能太大,所以你只需要输出答案在十进制表示下的最后 k 位即可。
输入输出格式
输入格式:
有多组数据,对于每组数据输入三个数a,b,k,分别代表小A抛硬币的次数,小B抛硬币的次数,以及最终答案保留多少位整数。
输出格式:
对于每组数据,输出一个数,表示最终答案的最后 k 位为多少,若不足 k 位以 0 补全。
题意:
小A可以抛a次硬币,小B可以抛b次硬币(a>=b)问小A抛出正面的次数比小B多的情况种数,输出对10的k次方取余(k<=9);
题解:
①这是一个利用对应关系进行构造的组合问题:
如果每一种小A赢情况对应(把a,b次抛出的结果正面变成反面)一种小B赢的情况,那么总可能数/2就是答案,但是事实上不是,在可能会有小A无论在两种情况下都是比小B多,或者小A在两种情况下都小于等于小B的次数,为此,就只有分a=b和a>b讨论。
②a=b
A和B掷出的正面相同,小A两种情况都赢不了
$F = \sum_{i=0}^{a}C_{a}^{i}C_{a}^{i}=\sum_{i=0}^{a}C_{a}^{i}C_{a}^{a-i} = C_{2a}^{a}$
(a选i个再在另外a个选a-i个和在2a个里选a个一一对应)
$ans = \frac{2^{2a}-F}{2} = \frac{2^{2a}-C_{2a}^{a}}{2}$
③a>b
A和B掷出的正面满足A>B且a-A>b-B时小A两种情况都可以赢小B
$G = \sum_{i=0}^{b}\sum_{j=1}^{a-b-1}C_{b}^{i}C_{a}^{i+j} = \sum_{i=0}^{b}\sum_{j=1}^{a-b-1}C_{b}^{b-i}C_{a}^{i+j} = \sum_{j=1}^{a-b-1}C_{a+b}^{j+b}$
(b个里选b-i个再在a个里选i+j个一一对应在a+b个里选b+j个)
$ans = \frac{2^{2a}+G}{2} = \frac{2^{2a}+\sum_{j=1}^{a-b-1}C_{a+b}^{j+b}}{2}$
剩下的组合数取模用扩展lucas就好了,只是稍稍有点变化。
1 #include<cstdio> 2 #include<iostream> 3 #define ll long long 4 #define Maxn 1000000001 5 #define RG register 6 #define il inline 7 using namespace std; 8 ll a,b,K,mod,mod2,mod5,v[2][2500005]; 9 ll pw(ll x,ll y,ll Mod){ 10 ll res = 1; 11 while(y){ 12 if(y&1) res = res * x % Mod; 13 y>>=1; x = x * x % Mod; 14 } 15 return res; 16 } 17 void init(ll k,ll mx){ 18 ll typ = k!=2; 19 v[typ][0] = 1; 20 for(RG ll i = 1;i <= mx;i++){ 21 if(i%k) v[typ][i] = v[typ][i - 1]*i % mx; 22 else v[typ][i] = v[typ][i - 1]; 23 } 24 } 25 inline void exgcd(ll a,ll b,ll &x,ll &y){ 26 if(!b) {x = 1,y = 0;} 27 else exgcd(b,a%b,y,x),y -= a/b*x; 28 } 29 ll inv(ll a,ll p){ 30 ll x,y; exgcd(a,p,x,y); 31 return (x%p+p)%p; 32 } 33 il ll mul(ll n,ll p,ll pk){ 34 if(!n) return 1; 35 ll ret = pw(v[p!=2][pk],n / pk,pk) * v[p!=2][n % pk] % pk; 36 return ret * mul(n / p,p,pk) % pk; 37 } 38 ll C(ll n,ll m,ll p,ll pk,ll fg){ 39 if(n<m) return 0; 40 ll cnt = 0; 41 for(RG ll i = n;i;i/=p) cnt += i / p; 42 for(RG ll i = m;i;i/=p) cnt -= i / p; 43 for(RG ll i = (n - m);i;i/=p) cnt -= i / p; 44 if(p==2&&fg) cnt--; 45 if(cnt>=K) return 0; 46 ll s1 = mul(n,p,pk),s2 = mul(m,p,pk),s3 = mul(n - m,p,pk); 47 ll ret = pw(p,cnt,pk) * s1 % pk * inv(s2,pk) % pk * inv(s3,pk) % pk; 48 if(p==5&&fg) ret = ret * inv(2,pk) % pk; 49 return ret * (mod / pk) % mod * inv(mod / pk,pk) % mod; 50 } 51 ll lucas(ll n,ll m,ll fg) {return (C(n,m,2,mod2,fg) + C(n,m,5,mod5,fg)) % mod;} 52 int main() 53 { //freopen("bzoj4830.in","r",stdin); 54 //freopen("bzoj4830.out","w",stdout); 55 init(2,512); init(5,1953125); 56 while(cin >> a >> b >> K){ 57 mod2 = pw(2,K,Maxn); mod5 = pw(5,K,Maxn); mod = pw(10,K,Maxn); 58 ll ans = pw(2,a + b - 1,mod); 59 if(a==b) ans = (ans - lucas(a+b,a,1) + mod) % mod; 60 else { 61 for(RG ll i = (a+b)/2+1;i<a;i++) ans = (ans + lucas(a+b,i,0))%mod; 62 if(!((a+b)%2)) ans = (ans + lucas(a+b,(a+b)/2,1)) % mod; 63 } 64 while(ans<mod/10) mod/=10,printf("0"); 65 printf("%lld\n",ans); 66 } 67 return 0; 68 }//by tkys_Austin;
(快省选了,关于扩lucas,扩gcd,扩CRT的叙述后面有时间可能会补上)
转载于:https://www.cnblogs.com/Paul-Guderian/p/8647074.html
bzoj4830 hnoi2017 抛硬币相关推荐
- bzoj 4830: [Hnoi2017]抛硬币 [范德蒙德卷积 扩展lucas]
4830: [Hnoi2017]抛硬币 题意:A投a次硬币,B投b次硬币,a比b正面朝上次数多的方案数,模\(10^k\). \(b \le a \le b+10000 \le 10^{15}, k ...
- [AH2017/HNOI2017]抛硬币
一.题目 点此看题 二.解法 前置芝士:范德蒙德卷积: C(n+m,k)=∑i=0kC(n,i)C(m,k−i)C(n+m,k)=\sum_{i=0}^kC(n,i)C(m,k-i)C(n+m,k)= ...
- 【扩展lucas】LOJ#2023. 「AHOI / HNOI2017」抛硬币
Description 抛硬币,小A投 a a a次,小B投 b b b次,求小A正面次数多于小B正面次数的方案数. 1 ≤ a , b ≤ 1 e 15 , 0 ≤ a − b ≤ 1 e 4 , ...
- 有道概率题:一个有趣的抛硬币问题
假设有一个硬币,抛出字(背面)和花(正面)的概率都是0.5,而且每次抛硬币与前次结果无关.现在做一个游戏,连续地抛这个硬币,直到连续出现两次字为止,问平均要抛多少次才能结束游戏?注意,一旦连续抛出两个 ...
- 抛硬币直到若干次(k次)连续正面向上的概率
文章目录 问题描述 说明 解答过程 问题描述 问题描述:抛一枚硬币,当出现连续的三次(或k次)正面向上的时候停止,问抛硬币的次数期望是多少? 说明 这个问题网上有很多答案,解释都不清楚,很多解释都误导 ...
- 抛硬币 直到连续出现两次字为止
题目: [plain] view plaincopy 假设有一个硬币,抛出字(背面)和花(正面)的概率都是0.5,而且每次抛硬币与前次结果无关.现在做一个游戏,连续地抛这个硬币,直到连续出现两次字为止 ...
- boost::math模块二项式分布来预测概率 抛硬币时的正面和反面的测试程序
boost::math模块二项式分布来预测概率 抛硬币时的正面和反面的测试程序 实现功能 C++实现代码 实现功能 boost::math模块二项式分布来预测概率 抛硬币时的正面和反面的测试程序 C+ ...
- Java黑皮书课后题第5章:5.40(模拟:正面或反面)编写程序,模拟抛硬币一百万次,显示出现正面和反面的次数
5.40(模拟:正面或反面)编写程序,模拟抛硬币一百万次,显示出现正面和反面的次数 题目 题目概述 破题 代码 运行示例 题目 题目概述 5.40(模拟:正面或反面)编写程序,模拟抛硬币一百万次,显示 ...
- 用贝叶斯来看看抛硬币的概率
前面介绍了贝叶斯学派的思想和先验分布.后验分布的相关知识,古典频率学派认为抛硬币的概率是常数,本文从贝叶斯学派的角度看待抛硬币的概率问题.本文详细介绍了 分布,重述贝叶斯思想,对于抛硬币的概率问题作 ...
最新文章
- 程序员大厂不一定要进,算法必须要学!收藏89篇精选算法文章
- 50 多万个项目陷入混乱!只因代码库许可协议不兼容
- Fedora 18 正式发布
- hook 与aspectj_将AspectJ与NetBeans平台开发集成
- 某Q娱乐网emlog程序整站源码
- php点击按钮弹窗提示,WEB表单,给出弹出框提示,点击按钮报错
- php定时执行代码漏洞_在CTF比赛中发现的PHP远程代码执行0day漏洞
- 差分输出和单端输出的区别(转载)
- 虚拟机中CentOS系统安装流程
- thinkpadt410接口介绍_ThinkPadT410全程拆解
- 有哪些不错的数学、物理类的「闲书」?
- 面向机器学习的自然语言标注2.4 语料库的规模
- 家庭电信网弄外网唤醒并远程内网电脑
- 你真的了解开源镜像站吗?
- html里子目录,技术宅文之还电脑屏幕原来的百富美姿态_html/css_WEB-ITnose
- 用cookie登录KinhDown教程
- 【硬件】常见芯片封装技术
- Arduino文档阅读笔记-4 WHEEL ROBOT CAR BASIC EXAMPLE
- 【教程】farmskins怎么玩
- Java选择与循环语句
热门文章
- java 三级考试_java web 学习 --第三天(Java三级考试)
- 斯坦德机器人收购_斯坦德机器人合伙人兼CMO王茂林:人是公司发展根本,多数企业都死于合伙人...
- 简述php中文件上传过程,简单php文件上传详细说明
- java accept charset_springmvc中post请求中文乱码问题
- c语言50到100套,c语言51-100套试题答案及详解.pdf
- 虚拟机centos7忘记密码怎么办_电脑忘记密码怎么办
- Apriltag可用图片:TAG16H5
- 2021-06-082021年春季学期-信号与系统-第十五次作业-第四小题参考答案
- 全国大学生智能汽车竞赛-讯飞赛道规则解读
- 电路纹身-疼痛的快乐