CF351B Jeff and Furik

Description 

给一个1~n的排列p[i],Jeff先手可以交换任意两个相邻元素,而Furik会有0.5的几率把任意满足p[i] < p[i+1]的p[i]和p[i+1]交换,有0.5的几率把任意满足p[i] > p[i+1]的p[i]和p[i+1]交换,问将整个序列变成升序所需的最小期望步数 

Input

第一行一整数n表示序列长度,之后一个1~n的排列p[i] (1<=n<=3000) 

Output 

输出把整个序列变成升序所需的最小期望步数 

Sample Input 

5
3 5 2 4 1

Sample Output 

13.000000 

Solution

考虑E[i](i为逆序对个数)的最小期望步数,则E[0]=0,E[1]=1;那么每一次Jeff肯定是交换使逆序对减少一个而Furik则有50%减少一个50%增加一个,故E[i]=1/2*(E[i-2]+1)+1/2*(E[i-1+1]+1);化简得E[i]=E[i-2]+4;

故模拟归并排序求一次逆序对个数便可实现。

Code

 1 #include<bits/stdc++.h>
 2 #define maxn 3005
 3 using namespace std;
 4 int n,a[maxn],t[maxn];
 5 int msort(int l,int r){
 6     if(l==r) return 0;
 7     
 8     int m=l+r>>1;
 9     int t1=msort(l,m);
10     int t2=msort(m+1,r);
11     
12     int t3=0;
13     int i=l,j=m+1,k=l;
14     while(i<=m&&j<=r){
15         if(a[i]>a[j]){
16             t3+=m-i+1;
17             t[k++]=a[j++];
18         }
19         else{
20             t[k++]=a[i++];//本来就应该小于 
21         }
22     }
23     while(i<=m) t[k++]=a[i++];
24     while(j<=r) t[k++]=a[j++];
25     
26     for(int p=l;p<=r;p++) a[p]=t[p];//调整
27     return t1+t2+t3; 
28 }
29 void init(){
30     scanf("%d",&n);
31     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
32     int nd=msort(1,n);
33     if(nd&1){
34         printf("%lf",(double)(2*nd-1));
35     }
36     else printf("%lf",(double)2*nd);
37 }
38 int main(){
39     init();
40     
41     return 0;
42 } 
原文地址:https://www.cnblogs.com/degage/p/9681704.html