CF258D Little Elephant and Broken Sorting
題意
題意翻譯
有一個\(1\sim n\)的排列,會進行\(m\)次操作,操作為交換\(a,b\)。每次操作都有\(50\%\)的概率進行。
求進行\(m\)次操作以后的期望逆序對個數。
\(n,m\le 1000\)
輸入輸出格式
輸入格式:
The first line contains two integers \(n\) and \(m\) \((1\leq n,m\leq 1000,n>1)\) — the permutation size and the number of moves. The second line contains \(n\) distinct integers, not exceeding \(n\) — the initial permutation. Next \(m\) lines each contain two integers: the \(i\)-th line contains integers \(a_{i}\) and \(b_{i}\) \((1\leq a_{i},b_{i}\leq n,a_{i}\neq b_{i})\) — the positions of elements that were changed during the \(i\)-th move.
輸出格式:
In the only line print a single real number — the answer to the problem. The answer will be considered correct if its relative or absolute error does not exceed \(10^{-6}\).
輸入輸出樣例
輸入樣例#1:
2 1
1 2
1 2
輸出樣例#1:
0.500000000
輸入樣例#2:
4 3
1 3 2 4
1 2
2 3
1 4
輸出樣例#2:
3.000000000
思路
這道題真的水。 --Mercury
完全想不到的狀態設計,感謝\(Mercury\)巨佬的指點。
定義\(f(i,j)\)為位置\(i\)上的數比位置\(j\)上的數大的概率。假設每次交換都是\(100\%\)成功的,不妨設這次交換的數的下標為\(a,b\),那么對于任意的\(f(i,a),f(i,b)\)就要被交換,\(f(a,i),f(b,i)\)也要被交換。可是當前交換的概率是\(50\%\)的,所以\(f(i,a),f(i,b)\)之間的差值要被分別減少\(50\%\),也就相當于\(f(i,a)=f(i,b)=(f(i,a)+f(i,b))\div 2\)。同理,\(f(a,i)=f(b,i)=(f(a,i)+f(b,i))\div 2\)。最后的逆序對期望,也就是\(\Sigma [i<j]f(i,j)\times 1\),也就是\(\Sigma [i<j]f(i,j)\)。
還要再胡扯兩句。 其實只要想出了\(f(i,j)\)這個東西,什么都簡單了,可是又會有幾個人能夠想到這種方法呢?完全沒有類似的情況作為參考,掌握了這道題卻又能給類似的題提供經驗(畢竟也沒有類似的題)。下一次見到了這種思維量大的題,還是不太能想得出。思維的活躍在\(OI\)中還是有很大的作用的啊!
AC代碼
#include<bits/stdc++.h>
#define RG register
using namespace std;
int n,m,a[1005];
double ans,f[1005][1005];
int read()
{RG int re=0;RG char ch=getchar();while(!isdigit(ch)) ch=getchar();while(isdigit(ch)) re=(re<<3)+(re<<1)+ch-'0',ch=getchar();return re;
}
int main()
{n=read(),m=read();for(RG int i=1;i<=n;i++) a[i]=read();for(RG int i=1;i<=n;i++)for(RG int j=i+1;j<=n;j++)if(a[i]>a[j]) f[i][j]=1.0;else f[j][i]=1.0;while(m--){RG int x=read(),y=read();if(x==y) continue;for(RG int i=1;i<=n;i++){if(i==x||i==y) continue;f[i][x]=f[i][y]=(f[i][x]+f[i][y])/2;f[x][i]=f[y][i]=(f[x][i]+f[y][i])/2;}f[x][y]=f[y][x]=0.5;}for(RG int i=1;i<=n;i++)for(RG int j=i+1;j<=n;j++)ans+=f[i][j];printf("%.8f",ans);return 0;
}