首页 > 其他分享 >CF1542E1 Abnormal Permutation Pairs (easy version) 题解

CF1542E1 Abnormal Permutation Pairs (easy version) 题解

时间:2023-09-16 11:12:56浏览次数:30  
标签:Pairs 前缀 int 题解 sum sp Abnormal len 逆序

CF1542E1 Abnormal Permutation Pairs (easy version) 题解

不会 Hard version

对于第一个限制字典序,我们可以考虑枚举前 \(i\) 位相同,然后考虑后 \(n-i\) 位。我们只需要保证 \(p_{i+1} < q_{i+1}\) 即可。

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

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

\[f_{len, len, k} = \sum_{j = 1}^{len-1} f_{len-1, j, k-(len-1)} \\ f_{len, j, k} = \sum_{t = 0}^{len-2} f_{len-1, j, k-t} (1 \leq j<len) \]

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

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

然后我们来考虑统计答案。我们设逆序对个数上界 \(mx = \frac{len \times (len-1)}{2}\),\(sp\)、\(sq\) 分别为 \(p\) 和 \(q\) 中后 \(len\) 位的逆序对个数,一个朴素的答案式子如下:

\[\sum_{len = 1}^{n} {n \choose len} (n-len)! \sum_{j = 1}^{len} \sum_{sp = 1}^{mx} \sum_{k = j+1}^{len} \sum_{sq = 0}^{sp-1} f_{len, j, sp} \times f_{len, k, sq} \]

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

显然是一个 \(O(n^7)\) 的式子。我们调整一下这个式子:

\[\sum_{len = 1}^{n} {n \choose len} (n-len)! \sum_{j = 1}^{len} \sum_{sp = 1}^{mx} f_{len, j, sp} \times (\sum_{k = j+1}^{len} \sum_{sq = 0}^{sp-1} f_{len, k, sq}) \]

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

简单版就做完了,复杂度 \(O(n^4)\)。

代码:

#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;
}

标签:Pairs,前缀,int,题解,sum,sp,Abnormal,len,逆序
From: https://www.cnblogs.com/frostwood/p/17706456.html

相关文章

  • CF1852B Imbalanced Arrays 题解
    CF1852BImbalancedArrays题解Links洛谷CodeforcesDescription对于一个给定的长度为\(n\)的数组\(A\),定义一个长度为\(n\)的数组\(B\)是不平衡的当且仅当以下全部条件满足:\(-n\leqB_{i}\leqn\)且\(B_{i}\ne0\)。即每个数在\([-n,n]\)内且不为\(0\)。......
  • LeetCode-Java题解 209. Minimum Size Subarray Sum
    题目地址:209.MinimumSizeSubarraySum解题思路:    看到这道题,心里本身是有双指针这个概念的,但是不知道怎么用,脑子里第一反应就是暴力解法,双for一把梭,然后时间就超时了...看了题解才知道滑动窗口这个解法,不禁直呼妙啊!感觉和双指针非常类似,其核心点在于避免了暴力算法的枚......
  • 题解 UVA1566 John
    题目描述两个人轮流取石子,每人每次可以\([1,a_i]\)个石子,最后取完石子的人为负。问最终谁会赢。具体思路若堆数为\(1\)且该堆数量为\(1\),先手必败。若堆数不为\(1\)且每堆数量都为\(1\),若有奇数堆,先手比败,否则,先手必胜。若堆数不为\(1\),转换为\(Nim\)游戏,判......
  • 洛谷题解 | P1046 陶陶摘苹果
    ​目录题目描述输入格式输出格式输入输出样例说明/提示题目思路AC代码题目描述陶陶家的院子里有一棵苹果树,每到秋天树上就会结出 10个苹果。苹果成熟的时候,陶陶就会跑去摘苹果。陶陶有个 30厘米高的板凳,当她不能直接用手摘到苹果的时候,就会踩到板凳上再试试。现......
  • 《特殊函数概论》Chapter 3习题解答
    《特殊函数概论》Chapter3习题解答卷心汪汪队众所周知,王竹溪、郭敦仁所著的《特殊函数概论》是一本对初学特殊函数的同学非常友好的书,特别是对我这种英语不好的人来讲,不用一边翻字典一边看Whittaker&Waston了但是据我所知,特殊函数概论应该是没有完整......
  • 题解 P8920 『MdOI R5』Variance
    题目描述给你两个长度为\(n\)的序列\(a\)和\(b\),让你选\(n\)个\(c_i\in[a_i,b_i]\),使得\(\frac{1}{n}\sum_{i=1}^n(c_i-\overlinec)^2\)最大。具体思路首先我们从方差的定义出发,方差代表了数据的波动程度,公式为:$$s^2=\frac{1}{n}\sum_{i=1}^n(a_i-\overline......
  • Fox and Minimal path 题解
    FoxandMinimalpath题目大意构造一张无向图,使得从\(1\)到\(2\)的最短路数量为\(k\)。思路分析我们首先可以发现当\(k=2^t\)时的构造方式:其中只有\(O(\logk)\)个点。当\(k\not=2^t\)时,我们可以将\(k\)二进制拆分,对于每一个二进制位重复上述操作,就可以得......
  • 课堂问题解答
    一、运行结果:由于浮点数在计算机内部的表示方式是有限的,所以在进行浮点数计算时可能会出现精度损失,导致结果不是准确的。在第一行代码中,计算0.05+0.01的结果,预期应该是0.06。然而,由于浮点数的精度限制,实际计算结果可能是一个近似值,例如0.060000000000000005。这就导致了打......
  • NOI 2023 题解
    CopperLoser的题解……Day1T1方格染色有一个\(n\timesm\)的网格,有\(Q\)次操作,每次形如有三种:将\((x_i+j,y_i)\)/\((x_i,y_i+j)\)/\((x_i+j,y_i+j)\)染色,其中\(j=0,1\dotsL_i-1\)。第三种操作至多只有\(5\)次,问之中有多少个格子被染过色。扫描线板子题,首先令......
  • 『题解』P6055
    给出\(N\),求:\[\sum_{i=1}^N\sum_{j=1}^N\sum_{p=1}^{\lfloor\frac{N}{j}\rfloor}\sum_{q=1}^{\lfloor\frac{N}{j}\rfloor}[\gcd(i,j)=1][\gcd(p,q)=1].\]考虑化简。存在一个性质,但是我当时推的时候忘记了。即:\[\sum_{i=1}^N\sum_{j=1}^N\su......