CF1542E2 Abnormal Permutation Pairs (hard version)

good tea。

对于两个排列 \(p,q\),如果 \(p\) 的字典序小于 \(q\),则要么 \(p_1<q_1\),要么存在一个 \(i\) 使得 \(p_{1\sim i}=q_{1\sim i}\) 且 \(p_{i+1}<q_{i+1}\),而后者可以转化为长度为 \(n-i\) 的排列 \(p',q'\) 满足 \(p'_1<q'_1\) 的方案数乘上 \(n^{\underline{i}}\)。因此,我们只需要对于每个 \(i\in[1,n]\) 计算长度为 \(i\) 的排列 \(p,q\) 满足 \(p_1<q_1\) 且 \(p\) 的逆序对个数大于 \(q\) 的方案数。

首先,我们可以枚举 \(p_1\) 和 \(q_1\),这样可以消除字典序的限制。它们对逆序对的贡献就分别为 \(p_1-1\) 和 \(q_1-1\)。如果再枚举 \(q_{2\sim n}\) 的逆序对个数 \(y\),那么符合限制的 \(p_{2\sim n}\) 的逆序对个数 \(x\) 应该满足 \(x+p_1-1>y+q_1-1\)。即 \(x>y+q_1-p_1\)。

根据上面的要求,我们设计 DP:设 \(f_{i,j}\) 为长度为 \(i\),逆序对数量为 \(j\) 的排列个数。转移方程很简单,因为从 \(i-1\to i\) 时只需要考虑 \(i\) 放在哪里:如果它放在倒数第 \(k\) 位,那么它对逆序对个数的贡献就是 \(k-1\)。因此转移方程为 \(f_{i,j}=\sum_{k=\max(0,j-i+1)}^jf_{i-1,k}\),显然可以前缀和优化到 \(n^3\)。

求出 \(f\) 后可以计算答案长度为排列长度为 \(n\) 时的答案了:记 \(s_{i,j}=\sum_{k=1}^j f_{i,k}\),\(m=\binom{n-1}{2}\),则答案为 \(\sum_{p_1=1}^{n-1}\sum_{q_1=p_1+1}^n\sum_{y=0}^{m-(q_1-p_1)}f_{n,y}\times(s_{n,m}-s_{n,y+q_1-p_1})\)。该部分时间复杂度为 \(n^4\),则总时间复杂度 \(n^5\),显然无法承受。

注意到我们不关系 \(p_1,q_1\) 的具体值,只关心 \(q_1-p_1\),因此可以枚举 \(d=q_1-p_1\),那么使 \(q_1-p_1=d\) 的 \(q_1,p_1\) 一共有 \(n-d\) 种情况。上述柿子变为 \(\sum_{d=1}^{n-1}\sum_{y=0}^{m-d}f_{n,y}\times (s_{n,m}-s_{n,y+d})\times (n-d)\)。总时间复杂度为 \(n^4\),还是无法承受。

那么继续拆柿子!此时我们只枚举 \(y\) 对于特定的 \(y\),\(f_{n,y}s_{n,m}(n-d)\) 显然可以把与 \(d\) 无关的 \(f_{n,y}s_{n,m}\) 用乘法分配律提出,那么因为 \(d\) 的上界为 \(t=\min(i-1,m-y)\),所以 \(\sum_{d=1}^t(n-d)\) 显然可以用等差数列求和公式快速求出,即为 \(\frac{(2n-1-t)t}{2}\)。

剩下来的 \(-f_{n,y}s_{n,y+d}(n-d)\) 似乎有些棘手。没关系,先把与 \(d\) 无关的 \(-f_{n,y}\) 提出,注意到 \(s_{n,y+d}(n-d)\) 中的 \(s_{n,y+d}\) 随着 \(d\) 的递增,其前面的系数是递减的。老套路了:把 \(n-d\) 拆成 \((n+y)-(y+d)\)。\(-s_{n,y+d}(y+d)\) 显然可以前缀和 \(sk_{n,j}=-\sum_{k=1}^js_{n,k}\times k\) 预处理出来;\(s_{n,y+d}(n-y)\) 把 \(n-y\) 提出来,预处理 \(s\) 的前缀和即可。

时间复杂度 \(n^3\)。代码中 \(y\) 的枚举上界是 \(m-d-1\) 而不是 \(m-d\),因为 \(y=m-d\) 时 \(s_{n,m}-s_{n,y+d}=s_{n,m}-s_{n,m}=0\),对答案无影响。代码中的 \(r\) 即为计算 \(-f_{n,y}s_{n,y+d}(n-d)\) 时 \(y+d\) 的上界。

#include <bits/stdc++.h>
using namespace std; const int N=505; int n,mod,ans,f[N][N*N/2],s[N][N*N/2],pp[N*N/2],ss[N*N/2]; int main(){
cin>>n>>mod,f[1][0]=s[1][0]=s[1][1]=1;
for(int i=2;i<=n;i++){
for(int j=0;j<=i*(i-1)/2;j++){
f[i][j]=(s[i-1][j]-(j<i?0:s[i-1][j-i])+mod)%mod;
s[i][j]=((j?s[i][j-1]:0)+f[i][j])%mod;
} ans=1ll*ans*i%mod;
for(int j=i*(i-1)/2+1;j<=i*(i+1)/2;j++)s[i][j]=s[i][j-1];
if(i<=3)continue;
int lim=(i-1)*(i-2)/2;
for(int j=0;j<=lim;j++){
tmpp[j]=((j==0?0:tmpp[j-1])-s[i-1][j]*j%mod+mod)%mod,
tmps[j]=((j==0?0:tmps[j-1])+s[i-1][j])%mod;
}
for(int j=0;j+2<=lim;j++){
int times=min(lim-j-1,i-1),c=(i-1+i-times)*times/2,r=min(lim-1,j+i-1);
ans=(ans+1ll*f[i-1][j]%mod*s[i-1][lim]%mod*c)%mod;
ans=(ans-1ll*f[i-1][j]*(pp[r]-pp[j]+(ss[r]-ss[j])*(i+j)%mod)%mod+mod)%mod;
}
}
cout<<ans<<endl;
return 0;
}

CF1542E2 Abnormal Permutation Pairs (hard version)的更多相关文章

  1. Codeforces 1542E2 - Abnormal Permutation Pairs (hard version)(DP)

    upd on 2021.7.7:修了个 typo Codeforces 题目传送门 & 洛谷题目传送门 首先考虑怎样处理"字典序小"这个问题,按照字典序比大小的套路,我们可 ...

  2. 洛谷 P5853 - [USACO19DEC]Tree Depth P(生成函数+背包)

    洛谷题面传送门 神仙题. 首先考虑一个点的深度是什么,注意到对于笛卡尔树而言直接从序列的角度计算一个点的深度是不容易的,因为这样会牵扯到序列中多个元素,需要 fixed 的东西太多,计算起来太复杂了. ...

  3. DP 做题记录 II.

    里面会有一些数据结构优化 DP 的题目(如 XI.),以及普通 DP. *I. P3643 [APIO2016]划艇 题意简述:给出序列 \(a_i,b_i\),求出有多少序列 \(c_i\) 满足 ...

  4. LeetCode解题报告—— Swap Nodes in Pairs & Divide Two Integers & Next Permutation

    1. Swap Nodes in Pairs Given a linked list, swap every two adjacent nodes and return its head. For e ...

  5. error: checker javascript/jshint: can’t parse version string (abnormal termination?)”

    vim 安装插件(k-vim方法 )好后 编辑js文件提示错误 可能是nodejs环境没搭建好 或者版本有误 用nvm安装node 后 需要 source ~/.bashrc 或者重新开一个终端 再运 ...

  6. one recursive approach for 3, hdu 1016 (with an improved version) , permutations, N-Queens puzzle 分类: hdoj 2015-07-19 16:49 86人阅读 评论(0) 收藏

    one recursive approach to solve hdu 1016, list all permutations, solve N-Queens puzzle. reference: t ...

  7. Create side-by-side stereo pairs in the Unity game engine

    Create side-by-side stereo pairs in the Unity game engine Paul BourkeDecember 2008 Sample Island pro ...

  8. ePass1000 Full ActiveX Control Reference Manual Version 2.0

    ePass1000 Full ActiveX Control Reference Manual Version 2.0 Error Code Value Return Status Descripti ...

  9. hdu 2583 permutation

    permutation Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tota ...

随机推荐

  1. FastAPI 学习之路(四十二)定制返回Response

    我们想要在接口中返回xml格式的内容,我们应该如何实现呢. from fastapi import FastAPI,Response @app.get("/legacy/") de ...

  2. 项目实战:Qt文件改名工具 v1.2.0(支持递归检索,搜索:模糊匹配,前缀匹配,后缀匹配;重命名:模糊替换,前缀追加,后缀追加)

    需求   在整理文件和一些其他头文件的时候,需要对其名称进行整理和修改,此工具很早就应该写了,创业后,非常忙,今天抽空写了一个顺便提供给学习.   工具和源码下载地址   本篇文章的应用包和源码包可在 ...

  3. 数据结构与算法-基础(十一)AVL 树

    AVL 树 是最早时期发明的自平衡二叉搜索树之一.是依据它的两位发明者的名称命名. AVL 树有一个重要的属性,即平衡因子(Balance Factor),平衡因子 == 某个节点的左右子树高度差. ...

  4. centOs7.6安装 mysql-8.0.27

    1.下载mysql 2.连接服务器 3.通过 rpm -qa | grep mariadb 命令查看 mariadb 的安装包 4.通过 rpm -e mariadb-libs-5.5.68-1.el ...

  5. Noip模拟39 2021.8.14

    T1 打地鼠 都切掉了的简单题 1 #include<bits/stdc++.h> 2 #define int long long 3 using namespace std; 4 con ...

  6. C++ 、Qt计算时间的方法

    原文链接:https://blog.csdn.net/chy555chy/article/details/53405072 Qt计算时间的两种方法: QTime elapsed() : ms QTim ...

  7. CCD摄像头视场角计算公式

    视场角大小和CCD传感器尺寸和镜头焦距有关: 水平视场角 = 2 × arctan(w / 2f); 垂直视场角 = 2 × arctan(h / 2f); 视场角 = 2 × arctan(d / ...

  8. 嵌入式单片机之stm32串口你懂了多少!!

    stm32作为现在嵌入式物联网单片机行业中经常要用多的技术,相信大家都有所接触,今天这篇就给大家详细的分析下有关于stm32的出口,还不是很清楚的朋友要注意看看了哦,在最后还会为大家分享有些关于stm ...

  9. A*,IDA*—高档次的暴搜

    A*通过评价函数来判断当前状态是否可以到达最终状态(即可行性剪枝),来减少不必要的搜索. 例题--P2324 [SCOI2005]骑士精神 我们通过当前不在指定位置上的棋子个数为评价函数,\(used ...

  10. hdu 1848 Fibonacci again and again (SG)

    题意: 3堆石头,个数分别是m,n,p. 两个轮流走,每走一步可以选择任意一堆石子,然后取走f个.f只能是菲波那契中的数(即1,2,3,5,8.....) 取光所有石子的人胜. 判断先手胜还是后手胜. ...