#dp,概率期望#AT4513 [AGC030D] Inversion Sum

题目


分析

考虑每次交换最多影响到(2n)个点对的逆序对判断
不妨设(dp[i][j])表示(a[i]>a[j])的概率,一开始按照(a)求出初始的(dp)
之后每次交换或不交换也就是概率等分,注意特判交换两个数的逆序对
以及最后答案乘上(2^Q)(一共有(2^Q)种可能的情况)


代码

#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
const int N=3011,mod=1000000007,inv2=(mod+1)>>1;
int n,Q,a[N],dp[N][N],f[N][N],ans,mi;
inline signed iut(){
	rr int ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
inline signed mo(int x,int y){return x+y>=mod?x+y-mod:x+y;}
signed main(){
	n=iut(),Q=iut(),mi=1;
	for (rr int i=1;i<=n;++i) a[i]=iut();
	for (rr int i=1;i<=n;++i)
	for (rr int j=1;j<=n;++j) dp[i][j]=a[i]>a[j];
	for (rr int i=1;i<=Q;++i,mi=mo(mi,mi)){
		rr int x1=iut(),x2=iut();
		for (rr int j=1;j<=n;++j) if (j!=x1&&j!=x2)
			f[x1][j]=f[x2][j]=1ll*inv2*mo(dp[x1][j],dp[x2][j])%mod,
			f[j][x1]=f[j][x2]=1ll*inv2*mo(dp[j][x1],dp[j][x2])%mod;
		for (rr int j=1;j<=n;++j) if (j!=x1&&j!=x2)
		    dp[x1][j]=f[x1][j],dp[x2][j]=f[x2][j],
		    dp[j][x1]=f[j][x1],dp[j][x2]=f[j][x2];
		dp[x1][x2]=dp[x2][x1]=1ll*inv2*mo(dp[x1][x2],dp[x2][x1])%mod;
	}
	for (rr int i=1;i<n;++i)
	for (rr int j=i+1;j<=n;++j)
	    ans=mo(ans,dp[i][j]);
	return !printf("%d
",1ll*ans*mi%mod);
}
原文地址:https://www.cnblogs.com/Spare-No-Effort/p/13763233.html