1. 程式人生 > >CodeForces 258D Little Elephant and Broken Sorting(期望)

CodeForces 258D Little Elephant and Broken Sorting(期望)

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