Here are the two atomic steps which need to be performed a number of times:
1) Randomly choose two indexes (l, r) with l < r and then swap (d[l], d[r]).
2) Randomly choose two indexes (l, r) with l < r and then reverse (d[l…r]) (both inclusive)
We can calculate these two steps separately, because of the linearity of the expectation, we can calculate the expected array after the first step (repeated a times): (A[0], A[1], …, A[n - 1]) and use this array as the input of the second step (repeated b times), then we can calculate the final answer based on the output at the end of the second step.
Solution for Step (1), i.e. swapping elements:
How does one compute the expected value of the element in the i-th position after Step (1)?
Let P(i, j, k) be the possibility that d[i] goes to the j-th position after executing Step (1) k times.
A[i] = P(i, i, n1) * d[i] + sum(P(j, i, n1) * d[j] (i != j))
// because all the operations are randomly chosen.
P(i, i, k) = P(0, 0, k)
P(j, i, k) = P(0, 1, k)
==> A[i] = P(0, 0, n1) * d[i] + P(0, 1, n1) * (sum - d[i])
P(0, 1, n1) = P(0, 2, n1) = … = P(0, n - 1, n1)
and
P(0, 0, n1) + P(0, 1, n1) + … + P(0, n - 1, n1) = P(0, 0, n1) + (n - 1) * P(0, 1, n1) = 1
==> P(0, 1, n1) = (1 - P(0, 0, n1)) / (n - 1).
So we only need to calculate P(0, 0, n1).
P(0, 0, k) = P(0, 0, k - 1) * P(unchanged) + P(0, 1, k - 1) * P(swap(0, 1)) + P(0, 2, k - 1) * P(swap(0, 2)) + … + P(0, n - 1, k - 1) * P(swap(0, n - 1))
Because P(0, 1, k) = P(0, 2, k) = … = P(0, n - 1, k), P(swap(0, 1)) = P(swap(0, 2)) = … = P(swap(0, n - 1))
//P(swap(0, 1)) = 1 / C(n, 2) //P(unchanged) + (n - 1) * P(swap(0, 1)) = 1 ==> P(unchanged) = (n - 2) / n.
==>
P(0, 0, k) = P(0, 0, k - 1) * P(unchanged) + P(0, 1, k - 1) * P(swap(0, 1)) * (n - 1) = P(0, 0, k - 1) * P(unchanged) + (1 - P(0, 0, k - 1)) * P(swap(0, 1)) = a * P(0, 0, k - 1) + b
F[k] = a * F[k - 1] + b
==> F[k] + r = a * (F[k] + r) //geometric progression ==> F[n1] + r = a ^ n1 * (1 + r) ==> F[n1] = a ^ n1 * (1 + r) - r
Solution for Step (2), i.e. reversing elements:
Because n2 is relatively small, so we can calculate the expected output array after each operation.
A0 A1 … An-1
The first problem to solve is: after executing one random reverse, what is the expected output?
Similar to the first step, we only need to calculate the P(i, j): the possibility that Ai goes to the jth position.
P(i, j) = number_of_reverse_intervals_swap(i, j) / C(n, 2)
number_of_reverse_intervals_swap(i, j) = min(i + 1, n - j).
Solution:
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <stack>
#include <queue>
#include <vector>
#include <cstdio>
#include <string>
#include <bitset>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <utility>
#include <sstream>
#include <iostream>
#include <algorithm>
#define sqr(x) ((x)*(x))
#define ABS(x) ((x<0)?(-(x)):(x))
#define eps (1e-13)
#define mp make_pair
#define pb push_back
#define Pair pair<int,int>
#define xx first
#define yy second
#define equal(a,b) (ABS((a)-(b))<eps)
using namespace std;
template<class T> string tostring(T x) { ostringstream out; out<<x; return out.str();}
long long toint(string s) { istringstream in(s); long long x; in>>x; return x; }
int dx[8]={0, 0, 1,-1, 1, 1,-1,-1};
int dy[8]={1,-1, 0, 0,-1, 1,-1, 1};
int kx[8]={1, 1,-1,-1, 2, 2,-2,-2};
int ky[8]={2,-2, 2,-2, 1,-1, 1,-1};
/////////////////////////////////////////////////////////////////////////////////////////////////////
int d[1000], n;
double p1, p2;
#define MAX 2
typedef struct matrix
{
int row,col;
double m[MAX][MAX];
matrix(int r,int c,int k)
{
row=r;
col=c;
for (int i=0;i<r;i++)
for (int j=0;j<c;j++)
m[i][j]=k;
}
matrix(){}
} matrix;
matrix operator *(matrix a,matrix b)
{
matrix c;
double t;
c.row=a.row; c.col=b.col;
for (int i=0;i<c.row;i++)
for (int j=0;j<c.col;j++)
{
t=0;
for (int k=0;k<a.col;k++)
t=(t+a.m[i][k]*b.m[k][j]);
c.m[i][j]=t;
}
return c;
}
matrix pow(matrix a,int k)
{
matrix c;
if (k==1) return a;
c = pow(a, k / 2);
c = c * c;
if (k % 2 == 0) return c;
else return c * a;
}
int ways(int cnt) {
return cnt * (cnt - 1) / 2;
}
void calc(int cnt) {
int tot = ways(n);
matrix m(2, 2, 0);
m.m[0][0] = (tot - n + 1.0) / tot; m.m[0][1] = (n - 1.0) / tot;
m.m[1][0] = 1.0 / tot; m.m[1][1] = (tot - 1.0) / tot;
m = pow(m, cnt);
p1 = m.m[0][0];
p2 = m.m[0][1];
}
double f[1000][1000]; // probability of j'th number being at i'th place after all operations
double g[1000][1000];
double sum1[1000][1001], sum2[1000][1001], sum3[1000][1001];
void calc2(int cnt) {
memset(f, 0, sizeof(f));
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
if (i == j) f[i][j] = p1;
else f[i][j] = p2 / (n - 1);
for (int iter = 0; iter < cnt; iter++) {
for (int c = 0; c < n; c++) {
sum1[c][0] = sum2[c][0] = sum3[c][0] = 0.0;
for (int i = 0; i < n; i++) {
sum1[c][i + 1] = sum1[c][i] + f[i][c];
sum2[c][i + 1] = sum2[c][i] + f[i][c] * (n - i) / (double) ways(n);
sum3[c][i + 1] = sum3[c][i] + f[i][c] * (i + 1) / (double) ways(n);
}
}
for (int i = 0; i < n; i++) {
for (int k = 0; k < n; k++) {
// same
g[i][k] += f[i][k] * (min(n - 1 - i, i) + ways(i) + ways(n - 1 - i)) / (double) ways(n);
if (n - i - 1 > i) g[i][k] += (sum1[k][n - i] - sum1[k][i + 1]) * (i + 1) / (double) ways(n); // i + 1 .. n - i - 1
if (n - i - 1 < i) g[i][k] += (sum1[k][i] - sum1[k][n - i - 1]) * (n - i) / (double) ways(n); // n - i - 1 .. i - 1
if (i != n - 1) g[i][k] += (sum2[k][n] - sum2[k][max(n - i - 1, i) + 1]); // max(n - i - 1, i)+1 .. n - 1
if (i != 0) g[i][k] += (sum3[k][min(n - i - 1, i)]); // 0 .. min(n - i - 1, i) - 1
}
}
memcpy(f, g, sizeof(g));
memset(g, 0, sizeof(g));
}
}
int main() {
// freopen("random.in", "r", stdin);
int n1, n2;
scanf("%d%d%d", &n, &n1, &n2);
for (int i = 0; i < n; i++)
scanf("%d", &d[i]);
calc(n1);
calc2(n2);
double res = 0.0;
for (int i = 0; i < n; i++) { // place
double p = ((i + 1) * (n - i) - 1.0) / (n * (n - 1) / 2.0);
for (int j = 0; j < n; j++) // number
res += d[j] * f[i][j] * p;
}
printf("%.9lf\n", res);
return 0;
}