題目連結:http://codeforces.com/problemset/problem/351/B
題意:
給你一個1到n的排列a[i]。
Jeff和Furik輪流操作,Jeff先手。
Jeff每次會交換a[i]>a[i+1]的兩個數。
Furik每次有1/2的概率交換a[i]<a[i+1]的兩個數,有1/2的概率交換a[i]>a[i+1]的兩個數。
當這個排列變成升序時,遊戲停止。
問你運算元的期望。
題解:
假設原序列中有t個逆序對。
那麼將這個序列變成升序,就是將這t個逆序對一個個消除。
Jeff每次會減少一個逆序對。
Furik每次有1/2概率增加一個逆序對,有1/2概率減少一個逆序對。
加起來就是:每兩次操作,有1/2概率減少兩個逆序對,有1/2概率不變。
也就是:每兩次操作,一定會減少一個逆序對。
然而在最後一個回合中,有可能Jeff操作完後,遊戲就已經結束了,不用Furik再操作。
當且僅當逆序對個數t為奇數時,上面的情況成立,運算元-1。
所以最終答案為:t*2 - (t&1)
另外這道題也可以遞推求期望,通項公式就是上面這個,原理一樣的。
還有保留6位小數什麼的,不存在的,重點是求逆序對QAQ……
AC Code:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #define MAX_N 3005 5 #define INF 1000000000 6 7 using namespace std; 8 9 int n,t=0; 10 int a[MAX_N]; 11 int l[MAX_N]; 12 int r[MAX_N]; 13 14 void merge(int lef,int mid,int rig) 15 { 16 int n1=mid-lef+1; 17 int n2=rig-mid; 18 for(int i=0;i<n1;i++) l[i]=a[lef+i]; 19 for(int i=0;i<n2;i++) r[i]=a[mid+i+1]; 20 l[n1]=r[n2]=INF; 21 for(int i=0,j=0,k=lef;k<=rig;k++) 22 { 23 if(l[i]<=r[j]) a[k]=l[i++]; 24 else a[k]=r[j++],t+=n1-i; 25 } 26 } 27 28 void merge_sort(int lef,int rig) 29 { 30 if(lef==rig) return; 31 int mid=(lef+rig)>>1; 32 merge_sort(lef,mid); 33 merge_sort(mid+1,rig); 34 merge(lef,mid,rig); 35 } 36 37 int main() 38 { 39 cin>>n; 40 for(int i=0;i<n;i++) cin>>a[i]; 41 merge_sort(0,n-1); 42 cout<<t*2-(t&1)<<".000000"<<endl; 43 }