Codeforces 351B Jeff and Furik:概率 + 逆序對【結論題 or dp】

Leohh發表於2018-01-04

題目連結: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 }

 

相關文章