Loading

CF1542E Abnormal Permutation Pairs

题意

给定一个 \(n\),求计数长度为 \(n\) 的排列 \(p,q\) 使得 \(p\) 字典序小于 \(q\) 并且 \(p\) 逆序对个数大于 \(q\)

Solution

感觉一直不太会这种排列的计数题。

对于不考虑字典序的情况,我们可以令 \(dp_{i,j}\) 表示前 \(i\) 个数构成排列有 \(j\) 个逆序对的方案数。这东西可以通过前缀和优化做到 \(O(n^3)\)

现在考虑字典序怎么限制。先转化一手题意,字典序小,意味着 \(p\) 从前往后第一个和 \(q\) 不一样的位置 \(i\),要满足 \(p_i<q_i\)。所以套路地枚举相等前缀的长度,然后考虑这段前缀的逆序对数,以及前缀与后缀产生的逆序对数,\(p,q\) 应该是相等的,所以我们就是希望能得到这段后缀中的逆序对数有 \(p>q\)

\(f_i\) 表示长度为 \(i\) 的排列在题目限制中的排列对数。

如果 \(p_1=q_1\),相当于在 \(i\) 个数中选一个放到最前面来,然后要求剩下的满足限制,注意到剩下的数离散后相当于是 \(i-1\) 的排列,所以有 \(f_i=i\times f_{i-1}\)

如果 \(p_1<q_1\),可以知道 \(p_1\) 与后面产生的逆序对数量是 \(p_1-1\),也可以知道 \(q_1\) 与后面产生的逆序对数量是 \(q_1-1\)。于是我们枚举 \(x,y\),表示的就是后面产生的逆序对个数。这样需要满足 \(x+p_1-1>y+q_1-1\)。能够知道当前 \(p_1,q_1\) 的方案数是:

\[calc(x,y)=\dfrac{(x-y+i)(i-x+y+1)}{2}+i\times (x-y-1) \]

然后再用上面那个 \(dp\) 直接求出逆序对数分别是 \(x,y\) 的方案数:

\[\sum_{x}\sum_{y}calc(x,y)\times dp_{i-1,x}\times dp_{i-1,y} \]

现在考虑一手复杂度,预处理 \(O(n^3)\),求 \(f\)\(O(n^5)\),可以通过 easy version。

枚举 \(x,y\) 实在是太难做了,只枚举 \(x\),然后枚举 \(p_1,q_1\),求出 \(dp\) 的前缀和 \(pre\),这样式子就变成了:

\[\sum_{x}\sum_{p_1=1}^i\sum_{q_1=p_1+1}^idp_{i-1,x}\times pre_{i-1,x+p_1-q_1-1} \]

发现后面这个东西应该只和 \(q_1-p_1\) 有关,我们令这个差值为 \(d\),则有:

\[\begin{aligned} f_i&=\sum_{x}\sum_{d=1}^{i-1}(i-d)\times dp_{i-1,x}\times pre_{i-1,x-d-1}\\ &=\sum_{x}dp_{i-1,x}\times \sum_{d=1}^{i-1}(i-d)\times pre_{i-1,x-d-1}\\ &=\sum_{x}dp_{i-1,x}\times (i\times \sum_{d=1}^{i-1}pre_{i-1,x-d-1}-\sum_{d=1}^{i-1}d\times pre_{i-1,x-d-1}) \end{aligned}\]

令:

\[sum1_{i,x}=\sum_{d=1}^{i}pre_{i,x-d}\\ sum2_{i,x}=\sum_{d=1}^{i}d\times pre_{i,x-d} \]

那么上式有:

\[f_i=\sum_{x}dp_{i-1,x}\times (i\times sum1_{i-1,x-1}-sum2_{i-1,x-1}) \]

现在需要快速求出 \(sum1,sum2\)。先求 \(sum1\)\(sum1_{i,0\sim i}\) 可以暴力做,此后递推:

\[sum1_{i,x}=sum1_{i,x-1}-pre_{i,x-1-i}+pre_{i,x-1} \]

\(sum2\),同样 \(sum2_{i,0\sim i}\) 可以暴力做,此后递推:

\[sum2_{i,x}=sum2_{i,x-1}+sum1_{i,x-1}-(i+1)\times pre_{i,x-1-i}+pre_{i,x-1} \]

Code

// Problem: 
//     Abnormal Permutation Pairs (hard version)
//   
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/CF1542E2
// Memory Limit: 2700 MB
// Time Limit: 500000 ms

#include<bits/stdc++.h>
#define ll long long
#define inf (1<<30)
#define INF (1ll<<60)
#define pb emplace_back
#define pii pair<int,int>
#define mkp make_pair
#define fi first
#define se second
#define all(a) a.begin(),a.end()
#define siz(a) (int)a.size()
#define clr(a) memset(a,0,sizeof(a))
#define rep(i,j,k) for(int i=(j);i<=(k);i++)
#define per(i,j,k) for(int i=(j);i>=(k);i--)
#define pt(a) cerr<<#a<<'='<<a<<' '
#define pts(a) cerr<<#a<<'='<<a<<'\n'
#define int long long
using namespace std;
const int MAXN=510;
int dp[2][MAXN*MAXN],pre[2][MAXN*MAXN],MOD;
int sum1[2][MAXN*MAXN],sum2[2][MAXN*MAXN];
int C2(int i){return i*(i-1)/2;}
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	int n,ans=0;cin>>n>>MOD;
	pre[1][0]=1;
	sum1[1][0]=sum2[1][0]=1;
	rep(i,2,n){
		memset(dp[i&1],0,sizeof(dp[i&1]));
		memset(pre[i&1],0,sizeof(pre[i&1]));
		memset(sum1[i&1],0,sizeof(sum1[i&1]));
		memset(sum2[i&1],0,sizeof(sum2[i&1]));
		rep(j,0,C2(i)){
			dp[i&1][j]=pre[(i-1)&1][min(C2(i-1),j)];
			if(j>=i) (dp[i&1][j]+=MOD-pre[(i-1)&1][min(C2(i-1),j-i)])%=MOD;
			if(j) pre[i&1][j]=pre[i&1][j-1];
			(pre[i&1][j]+=dp[i&1][j])%=MOD;
		}
		rep(x,0,min(C2(i),i)) rep(d,1,min(i,x))
			(sum1[i&1][x]+=pre[i&1][x-d])%=MOD,
			(sum2[i&1][x]+=d*pre[i&1][x-d]%MOD)%=MOD;
		rep(x,min(C2(i),i)+1,C2(i))
			sum1[i&1][x]=(sum1[i&1][x-1]+MOD-pre[i&1][x-1-i]+pre[i&1][x-1])%MOD,
			sum2[i&1][x]=(sum2[i&1][x-1]+sum1[i&1][x-1]+MOD-(i+1)*pre[i&1][x-1-i]%MOD+pre[i&1][x-1])%MOD;
		// rep(x,0,C2(i)) rep(d,1,min(i,x))
			// (sum1[i&1][x]+=pre[i&1][x-d])%=MOD,
			// (sum2[i&1][x]+=d*pre[i&1][x-d]%MOD)%=MOD;
		ans=ans*i%MOD;
		rep(x,1,C2(i-1))
			ans=(ans+dp[(i-1)&1][x]*(i*sum1[(i-1)&1][x-1]%MOD+MOD-sum2[(i-1)&1][x-1])%MOD)%MOD;
	}cout<<ans<<'\n';
	return 0;
}
posted @ 2022-11-14 22:08  ZCETHAN  阅读(15)  评论(0编辑  收藏  举报