题解 SP19148【INS14G - Kill them All】
SP19148【INS14G - Kill them All】
感觉其他博客讲的不是很清楚,也没有说组合数公式是怎么来的,我这样数论极菜的萌新看了好久才想明白qwq。。
还是先给出本题组合数公式C(n-1,n/2)
分析一
转化成坐标系上的移动方案问题
把第一个人杀的怪物看成横坐标,第二个人的看成纵坐标,怪物由第一个人杀向右走,反之向上走。
可知第一步一定向右,枚举终点的纵坐标m(即向上的步数),题目就变成从点(1,0)开始走到(n-m,m)不越过y=x的方案数。枚举向上步数m,总方案数为C(n-1,m)(n-1步中选m步),现在我们要减去非法方案数。
从(1,0)走到(n-m,m)的不合法方案按y=x翻转后与从(0,1)走到(n-m,m)的方案相对应
注意这里的翻转,终点是不翻转的,只翻转起点。
不合法方案为\(C_{n-1}^{m-1}\)(n-1步中向上走了m-1步),由此可知答案为\(C_{n-1}^m-C_{n-1}^{m-1}\)
公式(用i枚举终点纵坐标,0步没有不合法方案特判,0≤m(第二个人杀的次数)≤n/2):
\(C_{n-1}^0+\sum\limits_{i=1}^{\left\lfloor\frac{n}{2}\right\rfloor}(C_{n-1}^{i}-C_{n-1}^{i-1})=\sum\limits_{i=1}^{\left\lfloor\frac{n}{2}\right\rfloor}C_{n-1}^i-\sum\limits_{i=1}^{\left\lfloor\frac{n}{2}\right\rfloor-1}C_{n-1}^{i}=C_{n-1}^{\left\lfloor\frac{n}{2}\right\rfloor}\)(公式来自@Alpha)
得组合数公式C(n-1,n/2)
(感谢@Alpha提供的图例与分析!)
分析二
建议可以先看看关于卡特兰数的博客中对卡特兰数的应用,和这题很像,便于理解
把题目放到笛卡尔坐标系(平面直角坐标系)中考虑(如图1),x轴表示每个怪兽,从原点出发向右上方走表示由D杀了,向右下方走表示由S杀了。相当于我从原点出发,我的轨迹不能在过程中碰到x轴。
图1
可知第一步一定向上,所以原题转化为从原点出发,轨迹在过程中不能跑到x轴下面。
枚举向上步数m,总方案数为C(n-1,m),现在我们要减去非法方案数。对于非法的轨迹,有两种翻转方式:
把它第一次碰到y=-1前的轨迹按y=-1翻转(见P1641 [SCOI2010]生成字符串),也就是从(0,-2)到达原先的终点的方案与不合法方案一一对应,会发现向上走的步数比翻转前多1,即得C(n,m+1)
把它第一次碰到y=-1后的轨迹按y=-1翻转(如图2),在n,m确定的情况下,终点是确定的,翻转后的轨迹和原轨迹的方案一一对应。那么终点在哪里呢? 设p为翻转后终点纵坐标,m为翻转前的向上步数,则有m - (n - m) + p = -2 (n-m为向下走的步数,翻转前终点纵坐标+1=翻转后纵坐标的相反数-1)-> p = -2 + n - 2m ,设当向上走x步时可以到达p,则 x - (n - x) = -2 + n - 2m -> x = n - m - 1,由于翻转后的轨迹和原轨迹的方案一一对应,所以到达p的方案数就是不合法的方案数
所以非法方案数为C(n,n-m-1)=C(n,m+1),(见组合数中的互补性质,即从m个不同元素中取出n个元素的组合数=从m个不同元素中取出(m-n)个元素的组合数)
枚举向上步数为m,总方案数为C(n,m)-C(n,m+1);
公式(n已减1,n-1步没有不合法方案特判,n/2≤m(第一个人杀的次数)≤n-1):
\(C_{n-1}^{n-1}+\sum\limits_{i=\left\lfloor\frac{n}{2}\right\rfloor}^{n-2}(C_{n-1}^{i}-C_{n-1}^{i+1})=\sum\limits_{i=\left\lfloor\frac{n}{2}\right\rfloor}^{n-1}C_{n-1}^i-\sum\limits_{i=\left\lfloor\frac{n}{2}\right\rfloor+1}^{n-1}C_{n-1}^{i}=C_{n-1}^{\left\lfloor\frac{n}{2}\right\rfloor}\)(公式来自@Alpha)
答案为C(n-1,n/2)
图2
(以上思路由这个博客改进而来)
代码1
fac[i]存1~i的阶乘
inv[i]存1~i逆元的乘积
#include<cstdio>
using namespace std;
#define p 1000000007
long long fac[1000005],inv[1000005];
inline long long C(int n,int m) {
if (n==m || m==0) return 1;
return fac[n]*inv[m]%p*inv[n-m]%p;
}
int main() {
int T,n;
scanf("%d",&T),fac[0]=inv[0]=inv[1]=1;
for (int i=1; i<1000005; i++) fac[i]=fac[i-1]*i%p;
for (int i=2; i<1000005; i++) inv[i]=p-(p/i)*inv[p%i]%p;
for (int i=2; i<1000005; i++) inv[i]=inv[i-1]*inv[i]%p;
while(T--)
scanf("%d",&n),printf("%lld\n",C(n-1,n/2));
}
代码2
#include<cstdio>
using namespace std;
#define p 1000000007
#define int long long
int fac[1000005];
inline int pow(int x) {
int ans=1;
x%=p;
for (int i=p-2; i; i>>=1,x=x*x%p)
if (i&1) ans=ans*x%p;
return ans;
}//快速幂求逆元(x^(p-2))
signed main() {
int T,n;
scanf("%lld",&T),fac[0]=1;
for (int i=1; i<=1000005; i++) fac[i]=fac[i-1]*i%p;
while(T--)
scanf("%lld",&n),printf("%lld\n", fac[n-1]*pow(fac[n/2]*fac[n-1-n/2]%p)%p);
}
通过这题的确对组合数的应用加深了不少,如果分析有误还望指出qwq!
参考文章:
最后再次感谢@Alpha的耐心讲解与图例公式_
题解 SP19148【INS14G - Kill them All】的更多相关文章
- 「题解」:Kill
问题 A: Kill 时间限制: 1 Sec 内存限制: 256 MB 题面 题面谢绝公开. 题解 80%算法 赛时并没有想到正解,而是选择了另一种正确性较对的贪心验证. 对于每一个怪,我们定义它的 ...
- CSP-S 模拟测试 45 题解
由于咕掉的题解太多了,所以只能趁改完不动题的时间,来补补坑qwq,还是太弱了. 考试过程: 到新机房的第一次考试,貌似海星? 第一题一开始就觉得是个贪心,但以为所有小怪兽都要打完,所以想复杂了,但后来 ...
- 2014年亚洲区域赛北京赛区现场赛A,D,H,I,K题解(hdu5112,5115,5119,5220,5122)
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud 下午在HDU上打了一下今年北京区域赛的重现,过了5题,看来单挑只能拿拿铜牌,呜呜. ...
- LeetCode All in One题解汇总(持续更新中...)
突然很想刷刷题,LeetCode是一个不错的选择,忽略了输入输出,更好的突出了算法,省去了不少时间. dalao们发现了任何错误,或是代码无法通过,或是有更好的解法,或是有任何疑问和建议的话,可以在对 ...
- LeetCode Kill Process
原题链接在这里:https://leetcode.com/problems/kill-process/description/ 题目: Given n processes, each process ...
- Leetcode 简略题解 - 共567题
Leetcode 简略题解 - 共567题 写在开头:我作为一个老实人,一向非常反感骗赞.收智商税两种行为.前几天看到不止两三位用户说自己辛苦写了干货,结果收藏数是点赞数的三倍有余,感觉自己的 ...
- [CSP-S模拟测试97]题解
A.小盆友的游戏 感觉题解解释的很牵强啊……还是打表找规律比较靠谱 对于每个人,它构造了一个期望函数$f(x)$,设它的跟班个数为$cnt[x]$,那么令$f(x)=2^{cnt[x]}-1$(??鬼 ...
- [CSP-S模拟测试45]题解
开局一行$srand$,得分全靠随机化. A.kill 发现两个并不显然的性质: 1.选中的人和怪物一定是按顺序的.第一个人打所有被选中怪物的第一只,第二个人打第二只,$etc$. 2.最优方案打的怪 ...
- ORACLE快速彻底Kill掉的会话
在ORACLE数据库当中,有时候会使用ALTER SYSTEM KILL SESSION 'sid,serial#'杀掉一个会话进程,但是使用这个SQL语句杀掉会话后,数据库并不会立即释放掉相关的资源 ...
随机推荐
- git中设置代理
说明:在某种原因下,整个网络都是使用代理的情况下,需要使用git clone,这时就需要设置代理了. 在没有设置代理的时候,直接克隆报错 Failed to connect to gitee.com ...
- robotframework常见报错记录
1.'Response' object has no attribute '__getitem__':'Response'对象没有属性' getitem__' response对象的属性r.statu ...
- Mac使用pip命令安装selenium包报错解决方法
1.使用命令: pip install selenium 2.换成命令: python -m pip install selenium 即可成功安装
- 字节流和字符流的read方法
字节流和字符流的read方法 public class Test { public void fileOutput() throws Exception { File file = new File( ...
- opencv学习之颜色空间转换cvtColor()
我们生活中大多数看到的彩色图片都是RGB类型,但是在进行图像处理时,需要用到灰度图.二值图.HSV.HSI等颜色制式,opencv提供了cvtColor()函数来实现这些功能.首先看一下cvtColo ...
- 第三十六篇 入门机器学习——Jupyter Notebook中的魔法命令
No.1.魔法命令的基本形式是:%命令 No.2.运行脚本文件的命令:%run %run 脚本文件的地址 %run C:\Users\Jie\Desktop\hello.py # 脚本一旦 ...
- zabbix监控规划及实施
一.规划监控拓扑 二.主机分组 例:交换机.Nginx.Tomcat.MySQL 三.监控对象识别: 1.使用SNMP监控交换机 a.交换机开启snmp config -t snmp-server c ...
- 最大/最小de K个数/第K个数
题目 在未排序的数组中找到第 k 个最大的元素.请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素. 思路 堆排序 收获 用优先队列实现最大最小堆 注意下列代码中优先队列 ...
- c# excel 读写 64位操作系统 64位excel
用c#读写excel时,会出现 “本机未注册Microsoft.ACE.OLEDB.12.0 驱动(什么的,忘了)” 读写 64位的excel 时,要在项目属性里改一下目标平台,默认的为*86, 改为 ...
- pycharm pro与你同在
下载激活码和激活依赖的jar包,地址(https://www.lanzous.com/b00t4aneb密码:67t9)按照步骤操作即可第一步:正确安装 Pycharm 软件(版本2019.1.3 p ...