CF513G3 Inversions problem

Posted fhq_treap

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF513G3 Inversions problem相关的知识,希望对你有一定的参考价值。

考虑记\\(f_{i,j,k}\\)\\(k\\)次操作后,\\(i,j\\)位置被调换的概率。

那么我们考虑枚举我们要算的答案即\\((x,y)\\)

那么有\\(\\frac{n * (n + 1)}{2}\\)种调换顺序。

以此分类讨论:

一:不相交:

对答案不产生影响。

二:包含


因为是反转操作,考虑枚举枚举翻转移动的距离,从\\(f_{i + q,j + q,k - 1}\\)转移过来。

三:端点相交

同样考虑枚举反转距离 ,从\\(f_{i + q,j,k - 1}\\)还有\\(f_{i,j + q,k - 1}\\)

利用前缀和可以做到\\(O(k n^2)\\)

由于是实数运算,所以在\\(k\\)增大的过程中,\\(\\Delta ans\\to 0\\),所以我们取一个数据范围能够容忍的大数\\(k\\)作为答案,实测\\(k = 900\\)效果很不错。

CF513G3 Inversions problem
// code by fhq_treap
#include<bits/stdc++.h>
#define ll int
#define N 200

inline ll read(){
    char C=getchar();
    ll A=0 , F=1;
    while((\'0\' > C || C > \'9\') && (C != \'-\')) C=getchar();
    if(C == \'-\') F=-1 , C=getchar();
    while(\'0\' <= C && C <= \'9\') A=(A << 1)+(A << 3)+(C - 48) , C=getchar();
    return A*F;
}

ll n,k;
ll num[N];
double dp[N][N],tmp[N][N];

double calc(int x){return (double)(x) * (double)(x + 1) / 2;}

int main(){
	scanf("%d%d",&n,&k);
	for(int i = 1;i <= n;++i)
	scanf("%d",&num[i]);
//	for(int i = 1;i <= n;++i)
//	for(int j = i + 1;j <= n;++j)
//	dp[i][j] = 1.0;
	k = std::min((ll)900,k);
	double tot = (n + 1) * n / 2;
	for(int m = 1;m <= k;++m){
	for(int i = 1;i <= n;++i)
	for(int j = 1;j <= n;++j)
	tmp[i][j] = 0;
	for(int i = 1;i <= n;++i)
	for(int j = i + 1;j <= n;++j){
		tmp[i][j] = dp[i][j] * (calc(i - 1) + calc(j - i - 1) + calc(n - j)) / tot;
//        std::cout<<i<<" "<<j<<" "<<tmp[i][j]<<" "<<(calc(i - 1) + calc(j - i + 1) + calc(n - j))<<std::endl;
		//i,j
		for(int q = 1 - i;q + j <= n;++q)
		tmp[i][j] += (1 - dp[i + q][j + q]) * std::min(std::min(i,i + q),n - std::max(j,j + q) + 1) / tot;
//	    std::cout<<i<<" "<<j<<" "<<tmp[i][j]<<std::endl;
		//i
		for(int q = 1 - i;q < j - i;++q)
		tmp[i][j] += dp[i + q][j] * std::min(std::min(i,i + q),j - std::max(i,i + q)) / tot;
//	    std::cout<<i<<" "<<j<<" "<<tmp[i][j]<<std::endl;
		//j
		for(int q = i - j + 1;q + j <= n;++q)
		tmp[i][j] += dp[i][j + q] * std::min(std::min(j,j + q) - i,n - std::max(j + q,j) + 1) / tot;
//	    std::cout<<i<<" "<<j<<" "<<tmp[i][j]<<std::endl;
	}
	std::memcpy(dp,tmp,sizeof(tmp));
//	for(int i = 1;i <= n + 1;++i,puts(""))
//	for(int j = i + 1;j <= n;++j)
//	std::cout<<dp[i][j]<<\' \';
	}
 	double ans = 0.0;
	for(int i = 1;i <= n;++i)
	for(int j = i + 1;j <= n;++j){
		if(num[i] < num[j])ans += dp[i][j];
		else
		ans += 1 - dp[i][j];
	}
	std::printf("%.10f",ans);
}



以上是关于CF513G3 Inversions problem的主要内容,如果未能解决你的问题,请参考以下文章

CF749E Inversions After Shuffle 解题报告 (期望 树状数组)

CodeForces 749E: Inversions After Shuffle

CF316G3Good Substrings 后缀自动机

CF 316G3 Good Substrings——广义后缀自动机

iPhone SE容量改版513G!iPhone X是否也会这样搭配?

NAIPC 2016 K-Inversions I-Tourists