CF1542E1 Abnormal Permutation Pairs (easy version) 题解

CF1542E1 Abnormal Permutation Pairs (easy version) 题解

不会 Hard version

对于第一个限制字典序,我们可以考虑枚举前 i 位相同,然后考虑后 ni 位。我们只需要保证 pi+1<qi+1 即可。

我们设 len=ni。由于前 i 位完全相同,所以前 i 位内部的逆序对个数以及前 i 位与后 len 位之间产生的逆序对个数也是相同的,因此对于第二个条件,我们只需要满足 plen 位的逆序对个数严格大于 q 的后 len 位的即可。

因为逆序对仅与相对大小有关,所以后 len 位可以抽象成一个 1len 的排列。我们设 flen,j,k 表示长度为 len 的排列,第一位是 j,有 k 个逆序对的方案数。则长度每增加一位,只用考虑新加入的 len 作为开头以及其他数作为开头的转移。有:

flen,len,k=j=1len1flen1,j,k(len1)flen,j,k=t=0len2flen1,j,kt(1j<len)

对于第一种转移,我们只需把上一层所有数作为开头的方案加起来;对于第二种转移,我们考虑 len 插入到除了开头以外的其他位置产生的新的逆序对即可。

其中第二个转移是 O(n5) 的,我们发现枚举的 t 是一个区间内的答案,所以可以前缀和优化可以到 O(n4)

然后我们来考虑统计答案。我们设逆序对个数上界 mx=len×(len1)2spsq 分别为 pq 中后 len 位的逆序对个数,一个朴素的答案式子如下:

len=1n(nlen)(nlen)!j=1lensp=1mxk=j+1lensq=0sp1flen,j,sp×flen,k,sq

我们从 n 中选取 len 个数作为后缀,则剩下的 nlen 个数做前缀。前缀要求完全相同,但可以随意排列顺序。后半部分就是通过枚举来满足第一和第二个限制。

显然是一个 O(n7) 的式子。我们调整一下这个式子:

len=1n(nlen)(nlen)!j=1lensp=1mxflen,j,sp×(k=j+1lensq=0sp1flen,k,sq)

会发现后半部分是个矩形内的和,可以用二维前缀和优化到 O(1) 求出。前半部分枚举是 O(n4) 的。

简单版就做完了,复杂度 O(n4)

代码:

#include<bits/stdc++.h>
using namespace std;
const int N = 54;
int mod;
void add(int &a, int b) {
a = (a+b)%mod;
}
int f[N][N][N*N];
int n;
int fac[N];
int sum1[N][N][N*N];//第一个前缀和(可以滚动数组优化)
int sum2[N][N][N*N];//第二个前缀和(也可以滚动数组)
int C[N][N];
void prework() {
fac[0] = 1;
for(int i = 1; i<=n; ++i) {
fac[i] = 1ll*fac[i-1]*i%mod;
}
C[0][0] = 1;
for(int i = 1; i<=n; ++i) {
C[i][0] = 1;
for(int j = 1; j<=i; ++j) {
C[i][j] = (C[i-1][j] + C[i-1][j-1])%mod;
}
}//预处理阶乘和组合数
}
int main() {
scanf("%d%d", &n, &mod);
prework();
f[1][1][0] = 1;
for(int i = 2; i<=n; ++i) {
for(int j = 1; j<i; ++j) {
for(int k = i-1; k<=(i*(i-1)/2); ++k) {
add(f[i][i][k], f[i-1][j][k-(i-1)]);
}
}//新加入一个最大的数,让它作为开头
for(int j = 1; j<i; ++j) {
sum1[i-1][j][0] = f[i-1][j][0];
for(int o = 1; o<=(i*(i-1)/2); ++o) {
sum1[i-1][j][o] = f[i-1][j][o];
add(sum1[i-1][j][o], sum1[i-1][j][o-1]);
}//计算需要的前缀和
for(int o = 0; o<=(i*(i-1)/2); ++o) {
if(o > i-2) {
add(f[i][j][o], (sum1[i-1][j][o] - sum1[i-1][j][o-(i-2)-1])%mod);
if(f[i][j][o] < 0) f[i][j][o]+=mod;
} else f[i][j][o] = sum1[i-1][j][o];
}
}//对于其他数作为开头的情况
}
int ans = 0;
for(int i = 0; i<n-1; ++i) {
int ret = 1ll*fac[i]*C[n][i]%mod;
int len = n-i;
int sum = 0;
for(int j = 1; j<=len; ++j) {
sum2[len][j][0] = f[len][j][0];
add(sum2[len][j][0], sum2[len][j-1][0]);
for(int k = 1; k<=(len*(len-1)/2); ++k){
sum2[len][j][k] = f[len][j][k];
add(sum2[len][j][k], (1ll * sum2[len][j][k-1] + 1ll * sum2[len][j-1][k] + 1ll * mod - 1ll*sum2[len][j-1][k-1])%mod);
}
}//预处理二维前缀和。
for(int j = 1; j<=len; ++j) {
for(int oa = 1; oa<=(len*(len-1)/2) ;++oa) {
add(sum, 1ll*f[len][j][oa] * (1ll*sum2[len][len][oa-1] - sum2[len][j][oa-1])%mod);
}
}
add(ans, 1ll*ret*sum%mod);
}
if(ans<0) ans+=mod;
printf("%d\n", ans);
return 0;
}
posted @   霜木_Atomic  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示