Codeforces 1542E2 - Abnormal Permutation Pairs (hard version)(DP)
upd on 2021.7.7:修了个 typo
首先考虑怎样处理”字典序小“这个问题,按照字典序比大小的套路,我们可以枚举第一位 \(p_x\ne q_x\) 的位置 \(x\),那么必然有 \(p_x<q_x\),为了避免后面计算中出现太多形如 \(n-x\) 之类的东西,我们不枚举 \(x\),instead 我们枚举 \(i=n-x\),那么真正的 \(x\) 等于 \(n\) 减去你枚举的 \(i\)。
接下来考虑 \(p\) 逆序对个数大于 \(q\) 逆序对个数这个东西怎么处理,显然 \(p,q\) 的前 \(n-i-1\) 位是相同的,它们内部的逆序对个数是相同的,而由于 \(p,q\) 第 \(n-i\) 位到第 \(n\) 位中数组成相同,\(p,q\) 前 \(n-i-1\) 位与后 \(i+1\) 位之间的逆序对个数也相同,因此 \(p\) 逆序对个数大于 \(q\) 逆序对个数即意味着 \(p\) 后 \(i+1\) 位逆序对个数 \(>\) \(q\) 后 \(i+1\) 位逆序对个数。
我们假设 \(p\) 后 \(i\) 位逆序对个数为 \(u\),\(q\) 后 \(i\) 位逆序对个数为 \(v\),那么不难发现,加入 \(p_{n-i}\) 后逆序对个数的变化只与 \(p_{n-i}\) 在后 \(i+1\) 个数中排第几有关——我们假设 \(p_{n-i}\) 是 \(p\) 后 \(i+1\) 位中的第 \(s\) 小,\(q_{n-i}\) 是 \(q\) 后 \(n-i+1\) 位中的第 \(t\) 小,那么后 \(i+1\) 位中 \(p\) 的逆序对数即为 \(u+s-1\),\(q\) 的逆序对数即为 \(v+t-1\)。
我们考虑枚举 \(u,v\),那么根据 \(u+s-1>v+t-1\) 可知 \(t-s<u-v\),又显然 \(t>s\),故 \(0<t-s<u-v\),根据 \(t,s\in[1,i+1]\) 可知,满足 \(t-s=x(x\in[1,i])\) 的 \(t,s\) 共有 \(i+1-x\) 组,把它们累加起来可得 \(\sum\limits_{x=1}^{u-v-1}i+1-x=\dfrac{i(i+1)}{2}-\dfrac{(i+1-(u-v))(i+2-(u-v))}{2}\),我们记 \(f(i,x)=\dfrac{i(i+1)}{2}-\max(\dfrac{(i+1-x)(i+2-x)}{2},0)\),那么这东西就是 \(f(i,u-v)\)。
接下来考虑怎样计算答案,首先我们设 \(dp_{i,j}\) 表示有多少个长度为 \(i\) 的排列有 \(j\) 个逆序对,那么显然有转移方程式 \(dp_{i,j}=\sum\limits_{k=0}^{i-1}dp_{i-1,j-k}\),前缀和优化即可实现 \(\mathcal O(1)\) 转移。那么我们枚举 \(i,u,v\),那么根据之前的推论填好 \(p,q\) 后 \(i+1\) 位的相对大小关系的方案数为 \(\sum\limits_{u=0}^{i(i-1)/2}\sum\limits_{v=0}^{u-1}dp_{i,u}dp_{i,v}f(i,u-v)\),再乘上确定 \(p,q\) 前 \(n-i-1\) 位的方案数——选出 \(n-i-1\) 个数的方案数为 \(\dbinom{n}{n-i-1}\),将它们排列好的方案数为 \((n-i-1)!\),因此总方案数就是 \(\sum\limits_{i=0}^{n-1}\dbinom{n}{n-i-1}(n-i-1)!\sum\limits_{u=0}^{i(i-1)/2}\sum\limits_{v=0}^{u-1}dp_{i,u}dp_{i,v}f(i,u-v)\),暴力计算是 \(\mathcal O(n^5)\),无法通过 E2,可以通过 E1。如果稍微观察一下可知若 \(v<u-i\),\(f(i,u-v)=\dfrac{i(i+1)}{2}\) 为定值,可以直接一波前缀和带走,时间复杂度可以降到 \(n^4\),但是还是无法通过 E2。
附:E1 \(\mathcal O(n^4)\) 的做法,注意,由于模数不是质数,不能预处理阶乘及其逆元来求组合数,需手动递推。
const int MAXN=50;
const int MAXM=1225;
int n,mod,ans=0,dp[MAXN+5][MAXM+5],sum[MAXN+5][MAXM+5];
int c[MAXN+5][MAXN+5],fac[MAXN+5];
int main(){
scanf("%d%d",&n,&mod);dp[1][0]=1;
for(int i=0;i<=MAXM;i++) sum[1][i]=1;
for(int i=2;i<=n;i++){
for(int j=0;j<=i*(i-1)/2;j++){
dp[i][j]=sum[i-1][j];
if(j-i>=0) dp[i][j]=(dp[i][j]-sum[i-1][j-i]+mod)%mod;
// printf("%d %d %d\n",i,j,dp[i][j]);
} sum[i][0]=dp[i][0];
for(int j=1;j<=MAXM;j++) sum[i][j]=(sum[i][j-1]+dp[i][j])%mod;
}
for(int i=(fac[0]=1)-1;i<=MAXN;i++){
c[i][0]=1;if(i) fac[i]=1ll*fac[i-1]*i%mod;
for(int j=1;j<=i;j++) c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
}
for(int i=0;i<n;i++){
int lim=i*(i+1)/2,s=0;
for(int j=0;j<=i*(i-1)/2;j++){
s=(s+1ll*lim*sum[i][j-1]%mod*dp[i][j])%mod;
for(int k=max(0,j-i);k<j;k++){
s=(s-1ll*(i-j+k+1)*(i-j+k+2)/2*dp[i][k]%mod*dp[i][j]%mod+mod)%mod;
}
} //printf("%d\n",s);
ans=(ans+1ll*s*c[n][n-i-1]%mod*fac[n-i-1])%mod;
}
printf("%d\n",ans);
return 0;
}
接下来考虑优化这个做法,考虑后面这个式子 \(\sum\limits_{u=0}^{i(i-1)/2}\sum\limits_{v=0}^{u-1}dp_{i,u}dp_{i,v}f(i,u-v)\),我们不妨固定住 \(u\),考虑后面的东西怎么快速计算,我们不妨将 \(f\) 展开,可以得到:
&\sum\limits_{u=0}^{i(i-1)/2}\sum\limits_{v=0}^{u-1}dp_{i,u}dp_{i,v}f(i,u-v)\\
=&\sum\limits_{u=0}^{i(i-1)/2}dp_{i,u}·\sum\limits_{v=0}^{u-1}dp_{i,v}(\dfrac{i(i+1)}{2}-\max(\dfrac{(i+1-(u-v))(i+2-(u-v))}{2},0))\\
=&\sum\limits_{u=0}^{i(i-1)/2}dp_{i,u}·\sum\limits_{v=0}^{u-1}dp_{i,v}\dfrac{i(i+1)}{2}-dp_{i,u}·\sum\limits_{v=0}^{u-1}dp_{i,v}\max(\dfrac{(i+1-(u-v))(i+2-(u-v))}{2},0)
\end{aligned}
\]
前面的东西显然一波前缀和带走,对于后面的部分,如果 \(v<u-i\) 那显然是 \(0\),否则我们可以将 \(\max\) 展开,继续化为 \(\sum\limits_{v=0}^{u-1}dp_{i,v}·\dfrac{(i+1-u+v)(i+2-u+v)}{2}\),记 \(T=i+1+v\),那么原式 \(=\sum\limits_{v=0}^{u-1}dp_{i,v}·\dfrac{(T+v)(T+1+v)}{2}\),这里有一个稍微有些棘手的地方,就是 \(2\) 不一定有逆元,因此不能直接拆成 \(v\) 的平方项、\(v\) 的一次项和常数项分别求和再乘上 \(2\) 的逆元,因此我们采用这样一个方法:\(\dfrac{(T+v)(T+1+v)}{2}=\dfrac{T(T+1)}{2}+Tv+\dfrac{v(v+1)}{2}\),这样三项都是整数,就可以直接求和了,维护 \(dp_{i,v},v·dp_{i,v},\dfrac{v(v+1)}{2}·dp_{i,v}\) 的前缀和即可 \(\mathcal O(1)\) 计算上式。
时间复杂度 \(n^3\),代码不算难写。
const int MAXN=500;
const int MAXM=500*499/2;
int n,mod,ans=0,dp[MAXN+5][MAXM+5];
int sum[MAXM+5],_sum[MAXM+5],__sum[MAXM+5];
int c[MAXN+5][MAXN+5],fac[MAXN+5];
int sum0(int l,int r){if(l>r) return 0;return (sum[r]-((!l)?0:sum[l-1])+mod)%mod;}
int sum1(int l,int r){if(l>r) return 0;return (_sum[r]-((!l)?0:_sum[l-1])+mod)%mod;}
int sum2(int l,int r){if(l>r) return 0;return (__sum[r]-((!l)?0:__sum[l-1])+mod)%mod;}
int main(){
scanf("%d%d",&n,&mod);dp[1][0]=1;
for(int i=0;i<=MAXM;i++) sum[i]=1;
for(int i=2;i<=n;i++){
for(int j=0;j<=i*(i-1)/2;j++){
dp[i][j]=sum[j];
if(j-i>=0) dp[i][j]=(dp[i][j]-sum[j-i]+mod)%mod;
// printf("%d %d %d\n",i,j,dp[i][j]);
} memset(sum,0,sizeof(sum));sum[0]=dp[i][0];
for(int j=1;j<=MAXM;j++) sum[j]=(sum[j-1]+dp[i][j])%mod;
}
for(int i=(fac[0]=1)-1;i<=MAXN;i++){
c[i][0]=1;if(i) fac[i]=1ll*fac[i-1]*i%mod;
for(int j=1;j<=i;j++) c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
}
for(int i=0;i<n;i++){
int lim=i*(i+1)/2,s=0;
memset(sum,0,sizeof(sum));
memset(_sum,0,sizeof(_sum));
memset(__sum,0,sizeof(__sum));
sum[0]=dp[i][0];
for(int j=1;j<=i*(i-1)/2;j++){
sum[j]=(sum[j-1]+dp[i][j])%mod;
_sum[j]=(_sum[j-1]+1ll*j*dp[i][j])%mod;
__sum[j]=(__sum[j-1]+1ll*j*(j+1)/2*dp[i][j])%mod;
}
for(int j=0;j<=i*(i-1)/2;j++){
s=(s+1ll*lim*sum[j-1]%mod*dp[i][j])%mod;
int T=i-j+1;
int A=(1ll*T*(T+1)/2%mod+mod)%mod;
int B=(T+mod)%mod;
int minus=(1ll*A*sum0(max(0,j-i),j-1)%mod
+1ll*B*sum1(max(0,j-i),j-1)%mod
+sum2(max(0,j-i),j-1))%mod;
s=(s-1ll*minus*dp[i][j]%mod+mod)%mod;
} //printf("%d\n",s);
ans=(ans+1ll*s*c[n][n-i-1]%mod*fac[n-i-1])%mod;
}
printf("%d\n",ans);
return 0;
}
Codeforces 1542E2 - Abnormal Permutation Pairs (hard version)(DP)的更多相关文章
- Codeforces 1077F1 Pictures with Kittens (easy version)(DP)
题目链接:Pictures with Kittens (easy version) 题意:给定n长度的数字序列ai,求从中选出x个满足任意k长度区间都至少有一个被选到的最大和. 题解:$dp[i][j ...
- CF1542E2 Abnormal Permutation Pairs (hard version)
CF1542E2 Abnormal Permutation Pairs (hard version) good tea. 对于两个排列 \(p,q\),如果 \(p\) 的字典序小于 \(q\),则要 ...
- Codeforces Round #260 (Div. 2)C. Boredom(dp)
C. Boredom time limit per test 1 second memory limit per test 256 megabytes input standard input out ...
- Codeforces 1077F2 Pictures with Kittens (hard version)(DP+单调队列优化)
题目链接:Pictures with Kittens (hard version) 题意:给定n长度的数字序列ai,求从中选出x个满足任意k长度区间都至少有一个被选到的最大和. 题解:数据量5000, ...
- Codeforces 403D: Beautiful Pairs of Numbers(DP)
题意:转换模型之后,就是1~n个数中选k个,放到一个容量为n的背包中,这个背包还特别神奇,相同的物品摆放的位置不同时,算不同的放法(想象背包空间就是一个长度为n的数组,然后容量为1的物体放一个格子,容 ...
- CodeForces - 1183H Subsequences (hard version) (DP)
题目:https://vjudge.net/contest/325352#problem/C 题意:输入n,m,给你一个长度为n的串,然后你有一个集合,集合里面都是你的子序列,集合里面不能重复,集合中 ...
- Codeforces Problem - 38E - Let's Go Rolling!(DP)
E. Let's Go Rolling! time limit per test 2 seconds memory limit per test 256 megabytes input standar ...
- Codeforces Round #658 (Div. 2) D. Unmerge(dp)
题目链接:https://codeforces.com/contest/1382/problem/D 题意 给出一个大小为 $2n$ 的排列,判断能否找到两个长为 $n$ 的子序列,使得二者归并排序后 ...
- codeforces #260 DIV 2 C题Boredom(DP)
题目地址:http://codeforces.com/contest/456/problem/C 脑残了. .DP仅仅DP到了n. . 应该DP到10w+的. . 代码例如以下: #include & ...
随机推荐
- Dapr-服务调用
前言 上一篇对Dapr进行了了解,并搭建了Dapr环境.接下来就对Dapr的各个构建块类型的了解.应用实际案例. 一.服务调用: 在许多具有多个需要相互通信的服务的环境中,都会面临着很多问题. 如: ...
- 【c++ Prime 学习笔记】第11章 关联容器
关联容器的元素按照关键字来保存和访问,而顺序容器的元素是按照在容器中的位置来保存和访问 关联容器支持高效的关键字查找和访问 2种关联容器: map中的元素是关键字-值对(key-value对),关键字 ...
- 洛谷 P3195 [HNOI2008] 玩具装箱
链接: P3195 题意: 给出 \(n\) 个物品及其权值 \(c\),连续的物品可以放进一个容器,如果将 \(i\sim j\) 的物品放进一个容器,产生的费用是 \(\left(j-i+\sum ...
- 创建线程 出现SIGSEGV crash
在Opwrt平台上测试ok的一个网络传输延时测试demo程序移植到Android平台后,运行出现莫名其妙的SIGSEGV crash. 仔细检查过源码,特别是指针等后未发现问题. --------- ...
- Python matplotlib numpy 曼德尔布罗特集合 曼德尔布罗特 B.Madelbrot
import numpy as np import matplotlib.pyplot as plt def mandelbrot(h,w,maxit=20): y,x = np.ogrid[-1.4 ...
- 第06课 OpenGL 纹理映射
纹理映射: 在这一课里,我将教会你如何把纹理映射到立方体的六个面. 学习 texture map 纹理映射(贴图)有很多好处.比方说您想让一颗导弹飞过屏幕.根据前几课的知识,我们最可行的办法可能是很多 ...
- 设计模式学习-使用go实现原型模式
原型模式 定义 代码实现 优点 缺点 适用场景 参考 原型模式 定义 如果对象的创建成本比较大,而同一个类的不同对象之间差别不大(大部分字段都相同),在这种情况下,我们可以利用对已有对象(原型)进行复 ...
- VSCode PHP 开发环境配置 详细教程
VSCode PHP 开发环境配置 详细教程 这篇文章主要介绍了VScode+PHPstudy配置PHP开发环境的步骤,整理了官方以及优秀第三方的内容,对于学习和工作有一定借鉴意义. 配置过程 第一步 ...
- elasticsearch7.x配置文件
前言: 以下配置文件基于elasticsearch-7.13.4版本,当然也适用于其它7.x版本 集群环境: 部署3个节点的集群,各个节点不做角色区分,既是master,也是data,在性能 上这种方 ...
- 微信小程序小窗无效
这里算是踩过一个坑吧 1.自己的调试版本库是否在这个版本或者以上 2.编辑器是不能看到小窗效果的,只能在真机运行 3.播放的内容是否有效,是否能播放 4.跳转页面时内容是否处于播放状态 5.当前页面是 ...