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),现在我们要减去非法方案数。对于非法的轨迹,有两种翻转方式:

  1. 把它第一次碰到y=-1前的轨迹按y=-1翻转(见P1641 [SCOI2010]生成字符串),也就是从(0,-2)到达原先的终点的方案与不合法方案一一对应,会发现向上走的步数比翻转前多1,即得C(n,m+1)

  2. 把它第一次碰到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】的更多相关文章

  1. 「题解」:Kill

    问题 A: Kill 时间限制: 1 Sec  内存限制: 256 MB 题面 题面谢绝公开. 题解 80%算法 赛时并没有想到正解,而是选择了另一种正确性较对的贪心验证. 对于每一个怪,我们定义它的 ...

  2. CSP-S 模拟测试 45 题解

    由于咕掉的题解太多了,所以只能趁改完不动题的时间,来补补坑qwq,还是太弱了. 考试过程: 到新机房的第一次考试,貌似海星? 第一题一开始就觉得是个贪心,但以为所有小怪兽都要打完,所以想复杂了,但后来 ...

  3. 2014年亚洲区域赛北京赛区现场赛A,D,H,I,K题解(hdu5112,5115,5119,5220,5122)

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud 下午在HDU上打了一下今年北京区域赛的重现,过了5题,看来单挑只能拿拿铜牌,呜呜. ...

  4. LeetCode All in One题解汇总(持续更新中...)

    突然很想刷刷题,LeetCode是一个不错的选择,忽略了输入输出,更好的突出了算法,省去了不少时间. dalao们发现了任何错误,或是代码无法通过,或是有更好的解法,或是有任何疑问和建议的话,可以在对 ...

  5. LeetCode Kill Process

    原题链接在这里:https://leetcode.com/problems/kill-process/description/ 题目: Given n processes, each process ...

  6. Leetcode 简略题解 - 共567题

    Leetcode 简略题解 - 共567题     写在开头:我作为一个老实人,一向非常反感骗赞.收智商税两种行为.前几天看到不止两三位用户说自己辛苦写了干货,结果收藏数是点赞数的三倍有余,感觉自己的 ...

  7. [CSP-S模拟测试97]题解

    A.小盆友的游戏 感觉题解解释的很牵强啊……还是打表找规律比较靠谱 对于每个人,它构造了一个期望函数$f(x)$,设它的跟班个数为$cnt[x]$,那么令$f(x)=2^{cnt[x]}-1$(??鬼 ...

  8. [CSP-S模拟测试45]题解

    开局一行$srand$,得分全靠随机化. A.kill 发现两个并不显然的性质: 1.选中的人和怪物一定是按顺序的.第一个人打所有被选中怪物的第一只,第二个人打第二只,$etc$. 2.最优方案打的怪 ...

  9. ORACLE快速彻底Kill掉的会话

    在ORACLE数据库当中,有时候会使用ALTER SYSTEM KILL SESSION 'sid,serial#'杀掉一个会话进程,但是使用这个SQL语句杀掉会话后,数据库并不会立即释放掉相关的资源 ...

随机推荐

  1. JS高级---案例:验证表单

    案例:验证表单 <!DOCTYPE html> <html lang="en"> <head> <meta charset="U ...

  2. yii2验证规则

    验证规则 1.内置验证规则 [['sex', 'partner_id'], 'integer'], [['partner_id', 'camp_id',], 'required'], [['creat ...

  3. 与大神聊天1h

    与大神聊天1h 啊,与大神聊天1h真的是干货满满 解bug问题 之所以老出bug是因为我老是调用别人的包啊,在调参数的时候,并不知道内部机制 其实就自己写一个函数,然后能把功能实现就好了. 问题是,出 ...

  4. 部署Discuz和wordoress

    安装discuz 直接把安装包拷贝到根目录下 然后在浏览器中输入http://localhost/myweb/install/index.php 打开安装向导界面,需要修改一下myweb的权限 安全属 ...

  5. 10.pandas的替换和部分替换(replace)

    在处理数据的时候,很多时候会遇到批量替换的情况,如果一个一个去修改效率过低,也容易出错.replace()是很好的方法.   源数据 1.替换全部或者某一行 replace的基本结构是:df.repl ...

  6. python3爬虫(4)各种网站视频下载方法

    python3爬虫(4)各种网站视频下载方法原创H-KING 最后发布于2019-01-09 11:06:23 阅读数 13608 收藏展开理论上来讲只要是网上(浏览器)能看到图片,音频,视频,都能够 ...

  7. java简单学生成绩管理系统

    题目要求: 一. 数据结构要求:(5 分) 1.定义 ScoreInformation 类,其中包括七个私有变量(stunumber, name, mathematicsscore, englishi ...

  8. 搭建Python开发环境(Mac)

    准备 Python官网: https://www.python.org/ Python官方文档: https://docs.python.org/ 环境搭建 简介 pipenv是Python官方推荐的 ...

  9. MySQL加号+ 的作用

    案例:查询员工名和员工姓,连接成一个字段,并显示为: 姓名 SELECT last_name+first_name AS 姓名 FROM employees;没有报错但姓名一下全是0 Java中的 + ...

  10. 第五十四篇 Linux相关——远程连接SSH

        No.1. SSH(Secure Shell)安全外壳协议 建立在应用层基础上的安全协议 可靠,专为远程登录会话和其他网络服务提供安全性的协议 有效防止远程管理过程中的信息泄漏问题 SSH客户 ...