[atAGC054E]ZigZag Break
结论:(不妨假设$p_{1}<p_{n}$)$\{p_{i}\}$合法当且仅当$\exists 1\le i\le n-1$,使得$p_{1}\ge p_{i}$且$p_{i+1}\ge p_{n}$
充分性——
为了方便,在删除一个元素后,$i$和$n$也随之变化(指向原来的元素,若删除$p_{i}$或$p_{n}$会补充说明)
对$\{p_{1},p_{2},...,p_{i}\}$这个子问题不断删除(直至不能删除),显然最终必然是$p_{1}<p_{2}<...<p_{i}$(否则一定仍可以操作),同理可得后者也为$p_{i+1}>p_{i+2}>...>p_{n}$
如果$i\ge 3$或$i\le n-3$,不妨再删除$p_{i}$(并将$i$减小1)或删除$p_{i+1}$,重复此过程后即有$n-2\le i\le 2$,进而对$i$和$n$分类讨论,最终序列一定形如$\{2,1\},\{2,3,1\},\{1,3,2\}$或$\{2,1,4,3\}$,也即合法
必要性——
对$n$从小到大归纳,$n=2$时显然成立(取$i=1$即可)
考虑$n=k+1$时,反证若存在排列$\{p_{i}\}$合法但不存在$i$满足上述条件,假设其第一次删除的是$p_{i}$,由归纳假设删除后要存在$i$(满足上述条件),显然必然是$p_{1}\le p_{i-1}$且$p_{i+1}\ge p_{n}$
进而对$p_{i}$的值分类讨论,不难发现删除前也存在$i$,与假设矛盾,即得证
(类似地,在$p_{1}>p_{n}$时即要求$\exists 1\le i\le n-1$,使得$p_{1}\le p_{i}$且$p_{i+1}\le p_{n}$)
由于已经确定$p_{1}$,考虑枚举$p_{n}$(不妨仍假设$p_{1}<p_{n}$),并统计不合法的方案数——
将数分为三类,即$[1,p_{1}],(p_{1},p_{n}),[p_{n},n]$,那么即要求第三类数不接在第一类数的后面
初始序列中即有一个第一类数和第三类数(由于$n\ge 3$,这两个数一定不会相邻),并依次插入第2类、第1类和第3类数(注意顺序,并且要考虑初始的数),显然方案即
$$
(p_{n}-p_{1}-1)!\frac{(p_{n}-3)!}{(p_{n}-p_{1}-2)!}\frac{(n-p_{1}-2)!}{(p_{n}-p_{1}-2)!}=(p_{n}-p_{1}-1)\frac{(p_{n}-3)!(n-p_{1}-2)!}{(p_{n}-p_{1}-2)!}
$$
该式可以$o(1)$计算,但由于要枚举$p_{n}$,时间复杂度为$o(tn)$,无法通过
进一步的,枚举$k=p_{n}-p_{1}-2$,原式即
$$
(n-p_{1}-2)!\sum_{k=0}^{n-p_{1}-2}\frac{(k+1)(k+p_{1}-1)!}{k!}\\=(n-p_{1}-2)!\left(\sum_{k=0}^{n-p_{1}-2}\frac{(k+p_{1}-1)!}{k!}+\sum_{k=0}^{n-p_{1}-2}\frac{(k+p_{1}-1)!}{(k-1)!}\right)\\=(n-p_{1}-2)!\left((p_{1}-1)!\sum_{k=0}^{n-p_{1}-2}{k+p_{1}-1\choose p_{1}-1}+p_{1}!\sum_{k=0}^{n-p_{1}-2}{k+p_{1}-1\choose p_{1}}\right)\\=(n-p_{1}-2)!\left((p_{1}-1)!{n-2\choose p_{1}}+p_{1}!{n-2\choose p_{1}+1}\right)
$$
类似地,可以得到$p_{n}<p_{1}$的情况,答案为
$$
(p_{1}-3)!\left((n-p_{1})!{n-2\choose n-p_{1}+1}+(n-p_{1}+1)!{n-2\choose n-p_{1}+2}\right)
$$
时间复杂度为$o(t)$,可以通过

1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 1000005
4 #define mod 998244353
5 #define ll long long
6 int t,n,x,ans,fac[N],inv[N];
7 int C(int n,int m){
8 return (ll)fac[n]*inv[m]%mod*inv[n-m]%mod;
9 }
10 int main(){
11 fac[0]=inv[0]=inv[1]=1;
12 for(int i=1;i<N;i++)fac[i]=(ll)fac[i-1]*i%mod;
13 for(int i=2;i<N;i++)inv[i]=(ll)(mod-mod/i)*inv[mod%i]%mod;
14 for(int i=1;i<N;i++)inv[i]=(ll)inv[i-1]*inv[i]%mod;
15 scanf("%d",&t);
16 while (t--){
17 scanf("%d%d",&n,&x);
18 ans=fac[n-1];
19 if (x+2<=n){
20 int s=((ll)fac[x-1]*C(n-2,x)+(ll)fac[x]*C(n-2,x+1))%mod;
21 ans=(ans-(ll)fac[n-x-2]*s%mod+mod)%mod;
22 }
23 if (x>=3){
24 int s=((ll)fac[n-x]*C(n-2,n-x+1)+(ll)fac[n-x+1]*C(n-2,n-x+2))%mod;
25 ans=(ans-(ll)fac[x-3]*s%mod+mod)%mod;
26 }
27 printf("%d\n",ans);
28 }
29 return 0;
30 }
[atAGC054E]ZigZag Break的更多相关文章
- 【leetcode】ZigZag Conversion
题目简述 The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows ...
- 6. ZigZag Conversion
题目: The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows l ...
- leetcode problem 6 ZigZag Conversion
The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like ...
- Binary Tree Zigzag Level Order Traversal (LeetCode) 层序遍历二叉树
题目描述: Binary Tree Zigzag Level Order Traversal AC Rate: 399/1474 My Submissions Given a binary tree, ...
- [LeetCode] ZigZag Conversion [9]
称号 The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows li ...
- 字符串按照Z旋转90度然后上下翻转的字形按行输出字符串--ZigZag Conversion
The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like ...
- [Swift]LeetCode6. Z字形变换 | ZigZag Conversion
The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like ...
- LeetCode: 103_Binary Tree Zigzag Level Order Traversal | 二叉树Zigzag层次遍历 | Medium
本题也属于层次遍历的变形,不同之处在于其遍历的方法是交替进行的,形成一个ZigZag的曲线形式,如下: 代码如下: struct TreeNode { int val; TreeNode* left; ...
- C++ leetcode::ZigZag Conversion
mmp,写完没保存,又得重新写.晚上写了简历,感觉身体被掏空,大学两年半所经历的事,一张A4纸都写不满,真是一事无成呢.这操蛋的生活到底想对我这个小猫咪做什么. 今后要做一个早起的好宝宝~晚起就诅咒自 ...
随机推荐
- Java编译运行环境讨论(复古但能加深对Java项目的理解)
Java编译运行环境讨论(复古但能加深对Java项目的理解) 如今我们大多数情况都会使用IDE来进行Java项目的开发,而一个如今众多优秀的IDE已经能够帮助我们自动的部署并调试运行我们的Java程序 ...
- .NET Reflector软件破解
转自:https://blog.csdn.net/zxy13826134783/article/details/89057871 软件和注册机下载地址: 链接:https://pan.baidu.co ...
- SpringCloud升级之路2020.0.x版-27.OpenFeign的生命周期-创建代理
本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent 接下来,我们开始分析 OpenFeign 的生命周期,结合 OpenFeign 本身的源代 ...
- 【学习转载】MyBatis源码解析——日志记录
声明:转载自前辈:开心的鱼a1 一 .概述 MyBatis没有提供日志的实现类,需要接入第三方的日志组件,但第三方日志组件都有各自的Log级别,且各不相同,但MyBatis统一提供了trace.deb ...
- Android QMUI实战:沉浸式/适配状态栏
近期研究QMUI换肤的实现,顺便分析了下QMUI的沉浸式. 网上已有很多关于QMUI实现页面沉浸式的文章,简而言之:复杂了. 本期,我们仅通过几行代码,即可完美实现页面沉浸式效果,并轻松匹配换肤的色彩 ...
- Promise.resolve(x)中x有几种情况
ps:下面参数说的是Promise.resolve(x)中的x 一共四种情况: 1.如果参数是Promise实例本身,则抛出错误 2.如果参数是一个promise对象,则then函数的执行取决于这个参 ...
- python使用Django框架开发简单项目
一. (1)使用idea生成一个python项目,安装Django框架: pip install django==1.8.2 (2)初始化项目: django-admin startproject x ...
- [敏捷软工团队博客]Beta阶段发布声明
项目 内容 2020春季计算机学院软件工程(罗杰 任健) 博客园班级博客 作业要求 Beta阶段发布声明 我们在这个课程的目标是 在团队合作中锻炼自己 这个作业在哪个具体方面帮助我们实现目标 对Bet ...
- Seata分布式事务失败通知
一.背景 在我们使用Seata作为分布式事务时,有些时候我们的分布式时候并不是每次都可以成功的,而对于这些失败的分布式事务就需要进行通知.这篇文章简单记录一下如何实现通知. 二.功能实现 此处模拟邮件 ...
- 高斯消元de小板几
感觉就是模拟解方程,还比手动解方程笨一些.... 但是大数据的话,他毕竟比我解得快多了.... 1 inline int Gauss(int n){ 2 int cnt=1;//真实到达的行列式行数 ...