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 }