每個數隻有兩種情況,要麼在原來的位置上,要麼不在。
于是我們用一個簡單的dp求出兩種情況的機率。
f [ i ] [ 0 / 1 ] f[i][0/1] f[i][0/1]:Swap了 i i i次後,0表示不在原來位置上,1表示在,的機率。
轉移方程
- f [ i ] [ 1 ] = f [ i − 1 ] [ 1 ] ∗ ( n − 2 ) / n + f [ i − 1 ] [ 0 ] ∗ 2 / n / ( n − 1 ) f[i][1]=f[i-1][1]*(n-2)/n+f[i-1][0]*2/n/(n-1) f[i][1]=f[i−1][1]∗(n−2)/n+f[i−1][0]∗2/n/(n−1)
- f [ i ] [ 0 ] = f [ i − 1 ] [ 1 ] ∗ 2 / n + f [ i − 1 ] [ 0 ] ∗ ( 1 − 2.0 / n / ( n − 1 ) ) f[i][0]=f[i-1][1]*2/n+f[i-1][0]*(1-2.0/n/(n-1)) f[i][0]=f[i−1][1]∗2/n+f[i−1][0]∗(1−2.0/n/(n−1))
剩下的就很水了吧。隻要求出 i i i這個位置被子序列包含的機率就行了,這個就是 i ∗ ( n − i + 1 ) n ∗ ( n + 1 ) / 2 \frac{i*(n-i+1)}{n*(n+1)/2} n∗(n+1)/2i∗(n−i+1)
一開始因為沒開 l o n g l o n g long\ long long long FST了(;′⌒`)
#include <bits/stdc++.h>
#define fr(i,x,y) for(int i=x;i<=y;i++)
#define ll long long
using namespace std;
const int N=1000005;
double f[N][2];
ll n;
ll a[2505];
template<class T> void checkmin(T &a,const T &b) { if (b<a) a=b; }
template<class T> void checkmax(T &a,const T &b) { if (b>a) a=b; }
class TheSwapsDivOne {
public:
double find( vector <string> sequence, int k ) ;
};
double TheSwapsDivOne::find(vector <string> ss, int k) {
string s;
for(int i=0;i<ss.size();i++) s+=ss[i];
f[0][1]=1;n=s.size();
//cout<<n<<endl;
fr(i,1,k){
f[i][1]=f[i-1][1]*(n-2)/n+f[i-1][0]*2/n/(n-1);
f[i][0]=f[i-1][1]*2/n+f[i-1][0]*(1-2.0/n/(n-1));
}
ll sum=0,w;
fr(i,1,n) a[i]=s[i-1]-'0',sum+=a[i];
ll z=n*(n+1)/2;
double ans=0;
fr(i,1,n){
w=i*(n-i+1);
ans+=a[i]*f[k][1]*w;
ans+=w*(sum-a[i])*f[k][0]/(n-1);
}
ans/=z;
return ans;
}