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. [SUCTF 2019]EasySQL(堆叠注入配合sql_mode)

    考点:1.堆叠注入 2.set sql_mode=PIPES_AS_CONCAT;将||视为字符串的连接操作符而非或运算符 意外:注入* 复现: 1;set sql_mode=PIPES_AS_CON ...

  2. HTML /和./的区别 - Web开发

    "/"访问根目录 例1 https://www.cnblogs.com/test 里有 <a href="/Edsuns"></a> 则 ...

  3. 巨杉学习笔记 | SequoiaDB MySQL导入导出工具使用实战

    本文来自社区用户投稿,感谢这位小伙伴的技术分享 巨杉数据库架构简介 巨杉数据库作为分布式数据库是计算和存储分离架构,由数据库实例层和存储引擎层组成的.存储引擎层负责数据库核心功能比如数据读写存储以及分 ...

  4. kali 所有版本

    首先打开kali官方网站 第一步 第二步 找到 第三步点击标黄色的地方 http://cdimage.kali.org/ 第四步将网址中的cdimage替换为old http://old.kali.o ...

  5. sql查询 —— 分页

    -- 分页 -- limit -- limit start count (start 显示骑士值,单页数量) select *from student where gender=1 limit 6,3 ...

  6. sql查询——范围查询(区间查询)

    --范围查询(区间查询) --in() --查询年龄为18,28,38的人 select *from student where age=18 or age=28 or age=38; select ...

  7. 【转】继承了母版页的子页面中触发body的onload事件

    碰到有个继承了母版页的页面要加载body的onload事件,我发了一下午来解决这个问题,终于在国外某论坛上找到了解决方案 Method1: In the master page make the bo ...

  8. 【NOI2002】银河英雄传说

    [NOI2002]银河英雄传说 这道题暴力模拟会TLE,因为它是并查集的一个应用…… #include<bits/stdc++.h> using namespace std; ],q[], ...

  9. Dockerfile深度剖析

    Dockerfile主要是用来定制镜像   Dockerfile指令集 FROM ###指定基础镜像第一条指令.scratch是虚拟的镜像,表示一个空白的镜像. FROM centos:7.5 MAI ...

  10. 2 request的get和post方法

    requests的get方法 1 在百度里面查询关键字的方法,并获取带百度当前页面 import requests keywords = input('请输入>>>').strip( ...