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

题面

BZOJ

洛谷

题解

暴力是啥?

枚举\(A\)的次数和\(B\)的次数,然后直接组合数算就好了:\(\displaystyle \sum_{i=0}^a{a\choose i}\sum_{j=0}^{i-1}{b\choose j}\)。

完美\(TLE\)。

先考虑特殊点的情况,如果\(a=b\),那么显然两者输赢的情况反过来是一一对应的,所以答案就是总情况减去平局的情况除二,而总方法就是\(\displaystyle 2^{a+b}\)。考虑平局的情况。枚举两个人正面朝上的个数就好了,也就是\(\displaystyle \sum_{i=0}^a {a\choose i}^2={2a\choose a}\)。

证明?换个写法:\(\displaystyle \sum_{i=0}^a {a\choose i}{a\choose a-i}\)。这样组合意义就很明显了,即把当前的\(2a\)个东西分成左右两半,要选\(a\)个出来,那么就枚举左半边选了几个,乘起来就好啦。

好啦,上面怎么计算\(a=b\)的情况就很简单了,也就是\(\displaystyle \frac{2^{2a}-{2a\choose a}}{2}\)。

考虑怎么计算\(a>b\)的情况。我们前面\(a=b\)这么做的原因是什么呢?如果我们把一个非平局情况的整个抛硬币的结果全部翻转,那么必定对应这一种胜负情况相反的方案。

但是现在\(a>b\),那么在\(a-b\)的这部分硬币可能存在一些正面,使得最终\(A\)仍然获胜。

我们仍然想采用之前计算\(a=b\)的方法,总方案还是\(2^{a+b}\),然后我们直接除掉二,这样就会少算一些本来是\(A\)赢,翻转过来还是\(A\)赢的情况。所以要把这样的情况数给加上,再来除二。

考虑这样的情况的方案数,假装\(B\)有\(x\)个正面朝上,\(A\)正面朝上的次数是\(y\)。那么就要满足\(b-x<a-y\),也就是\(a-b>y-x\),因为本身就要\(A\)赢,所以还有\(y>x\)。

行,来枚举一下:\(\displaystyle \sum_{i=0}^b{b\choose i}\sum_{j=1}^{a-b-1}{a\choose i+j}\)

这是个什么鬼玩意???

行,来重新写下:\(\sum_{j=1}^{a-b-1}\displaystyle \sum_{i=0}^b{b\choose b-i}{a\choose i+j}\)

恩,又来了,把东西分成左右两半,一共要选\(j\)个出来。

所以式子这个玩意继续化简就是:\(\displaystyle \sum_{j=1}^{a-b-1}{a+b\choose j}\)

至于这个化简其实就是范德蒙德卷积。。。。。

那就可以把答案式给写出来了:\(\displaystyle \frac{2^{a+b}+\sum_{j=1}^{a-b-1}{a+b\choose j}}{2}\)。

模数蛋疼无比,强行给套上一个拓展卢卡斯。

然后就是各种卡常之旅了。这个东西除二肯定没有逆元,所以在算组合数的过程中就要除二。

首先后面那个组合数发现\(\displaystyle {a+b\choose j}={a+b\choose a+b-j}\),然后组合数又关于\((a+b)/2\)对称,所以组合数只需要算一半。

然后如果\(a+b\)是偶数的话还需要特殊算\(\displaystyle{a+b\choose \frac{a+b}{2}}\)。

注意一下组合数如果本身就要取模的话,就在算\(5^k\)的求逆,\(2^k\)的时候直接除二。。。

我的代码又臭又长QwQ

#include<iostream>
#include<cstdio>
using namespace std;
#define ll long long
inline ll read()
{
ll x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int fpow(int a,int b){int s=1;while(b){if(b&1)s*=a;a*=a;b>>=1;}return s;}
int fpow(int a,ll b,int MOD){int s=1;while(b){if(b&1)s=1ll*s*a%MOD;a=1ll*a*a%MOD;b>>=1;}return s;}
void exgcd(int a,int b,ll &x,ll &y){if(!b){x=1;y=0;return;}exgcd(b,a%b,y,x);y-=a/b*x;}
int inv(ll n,ll m){ll x,y;exgcd(n,m,x,y);x=(x%m+m)%m;return x;}
int fac[5],pw[5],tot=0;
int jc[3][2000000];
int JC(ll n,int p,int MOD,int id)
{
if(!n)return 1;
int ret=JC(n/p,p,MOD,id);
if(n>MOD)ret=1ll*ret*fpow(jc[id][MOD]%MOD,n/MOD,MOD)%MOD,n%=MOD;
ret=1ll*ret*jc[id][n]%MOD;
return ret;
}
ll a,b;int k,P;int pw2,pw5;
int C(ll n,ll m,int p,int pk,bool div)
{
if(n<0||m<0||n<m)return 0;
ll zero=0;
for(ll i=n;i;i/=p)zero+=i/p;
for(ll i=m;i;i/=p)zero-=i/p;
for(ll i=n-m;i;i/=p)zero-=i/p;
if(p==2&&div)--zero;
if(zero>=k)return 0;
int a=JC(n,p,pk,1+(p==5));
int b=1ll*JC(m,p,pk,1+(p==5))*JC(n-m,p,pk,1+(p==5))%pk;
a=1ll*a*inv(b,pk)%pk*fpow(p,zero)%pk;
if(p==5&&div)a=1ll*a*(pk+1)/2%pk;
return 1ll*a*(P/pk)%P*inv(P/pk,pk)%P;
}
int exLucas(ll n,ll m,bool d){return (C(n,m,2,pw2,d)+C(n,m,5,pw5,d))%P;}
void output(int x)
{
if(k==1)printf("%.1d\n",x);if(k==2)printf("%.2d\n",x);if(k==3)printf("%.3d\n",x);
if(k==4)printf("%.4d\n",x);if(k==5)printf("%.5d\n",x);if(k==6)printf("%.6d\n",x);
if(k==7)printf("%.7d\n",x);if(k==8)printf("%.8d\n",x);if(k==9)printf("%.9d\n",x);
}
int main()
{
fac[1]=2;fac[2]=5;pw[1]=pw[2]=9;tot=2;
for(int i=1;i<=tot;++i)
{
int MOD=fpow(fac[i],pw[i]);jc[i][0]=1;
for(int j=1;j<=MOD;++j)jc[i][j]=1ll*jc[i][j-1]*(j%fac[i]?j:1)%MOD;
}
while(scanf("%lld%lld%d",&a,&b,&k)!=EOF)
{
P=fpow(10,k);pw[1]=pw[2]=k;pw2=fpow(2,k);pw5=fpow(5,k);
int ans=fpow(2,a+b-1,P);
if(a==b)ans=(ans+P-exLucas(a+b,a,1))%P;
else
{
for(ll i=(a+b)/2+1;i<a;++i)
ans=(ans+exLucas(a+b,i,0))%P;
if((a+b)%2==0)ans=(ans+exLucas(a+b,(a+b)/2,1))%P;
}
output(ans);
}
return 0;
}

【BZOJ4830】[HNOI2017]抛硬币(组合计数,拓展卢卡斯定理)的更多相关文章

  1. bzoj4830 hnoi2017 抛硬币

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

  2. BZOJ4830 [Hnoi2017]抛硬币 【扩展Lucas】

    题目链接 BZOJ4830 题解 当\(a = b\)时,我们把他们投掷硬币的结果表示成二进制,发现,当\(A\)输给\(B\)时,将二进制反转一下\(A\)就赢了\(B\) 还要除去平局的情况,最后 ...

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

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

  4. 【BZOJ3129】[SDOI2013]方程(容斥,拓展卢卡斯定理)

    [BZOJ3129][SDOI2013]方程(容斥,拓展卢卡斯定理) 题面 BZOJ 洛谷 题解 因为答案是正整数,所先给每个位置都放一个就行了,然后\(A\)都要减一. 大于的限制和没有的区别不大, ...

  5. 【BZOJ2142】礼物(拓展卢卡斯定理)

    [BZOJ2142]礼物(拓展卢卡斯定理) 题面 BZOJ 洛谷 题解 显然如果\(\sum w_i>n\)无解. 否则答案就是:\(\displaystyle \prod_{i=1}^m{n- ...

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

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

  7. bzoj 4830: [Hnoi2017]抛硬币

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

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

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

  9. [AH/HNOI2017]抛硬币

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

随机推荐

  1. Lean Data Innovation Sharing Salon(2018.09.15)

    时间:2018.09.15地点:北京国华投资大厦

  2. Asp.net MVC 中Ajax的使用

    Asp.net MVC 抛弃了Asp.net WebForm那种高度封装的控件,让我们跟底层的HTML有了更多的亲近.可以更自由.更灵活的去控制HTML的结构.样式和行为.而这点对于Ajax 的应有来 ...

  3. Jmeter(三十四)_Beanshell解析并提取json响应

    1:前置条件 将fastjson-1.2.49.jar包置于jmeter的lib目录下,并将该jar包添加到测试计划的Library中:否则会报:Typed variable declaration ...

  4. 大话重构连载15:采用Mock技术完成测试

    第五次重构我们引入了数据库的设计,用户信息要从数据库中读取,问候语库存储在数据库中,并支持添加与更新.数据库的引入使自动化测试变得困难了,因为数据状态总是变化着的,而这种变化使得测试过程不能复现,这是 ...

  5. vue-cli中的check-versions.js配置文件包括semver,chalk,shell插件的解释

    本文介绍vue-cli脚手架build目录中check-versions.js的配置 本文件是用来检测node和npm版本的 直接上代码加注释 // 下面的插件是chalk插件,他的作用是在控制台中输 ...

  6. PairProject-电梯调度程序结对编程

    结对编程人员:184/050 1 结对编程 1.1 结对编程的优缺点 优点: ● 与单独开发相比,结对能够使人们在压力之下保持更好的状态.结对编程鼓励双方保持代码的高质量,即使在出现了让人不得不飞快地 ...

  7. Linux内核分析——可执行程序的装载

    链接的过程 首先运行C预处理器cpp,将C的源程序(a.c)翻译成ASCII码的中间文件(a.i) 接着C编译器ccl,将a.i翻译成ASCII汇编语言文件a.s 接着运行汇编器as,将a.s翻译成可 ...

  8. 《Linux内核分析》第六周学习笔记

    <Linux内核分析>第六周学习笔记 进程的描述和创建 郭垚 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/co ...

  9. 20150401 作业2 结对 四则运算(Doing)

    import java.util.ArrayList; import java.util.Random; import java.util.Scanner; public class SE2_1 {/ ...

  10. 小学四则运算APP 第一个冲刺阶段 第六天

    团队成员:陈淑筠.杨家安.陈曦 团队选题:小学四则运算APP 第一次冲刺阶段时间:11.17~11.27 本次发布的是重新排列整齐ResultActivity的布局代码activity_result. ...