【NOIP2013模拟9.29】TheSwaps(期望概率)

No.10 【NOIP2013模拟9.29】TheSwaps
  • 又是一道期望题.

  • 一个套路:\[Ans=\sum a_i*c_i\]

  • 其中,\(a_i\)表示\(k\)轮变换后第\(i\)个位置上的期望值.

  • 其中,\(c_i\)表示\(i\)这个位置被选到的概率,其实就是\[\frac{i*(n-i+1)}{n*(n+1)*\frac{1}{2}}\].

  • 然后我们很容易列出转移,其实就是看第\(k\)轮交换完之后如果一个位置上的数值为\(a_i\),那么再进行一轮交换,它的数值就变为\[a_i*\frac{n-2}{n}+\frac{2}{n*(n-1)}*(sum- a_i)\]

  • 其中,\(\frac{n-2}{n}\)是第\(i\)个数不选到的概率,其实就是\[\frac{n-1}{n}·\frac{n-2}{n-1}=\frac{n-2}{n}\]

  • 然后被选到的概率显然是\(\frac{2}{n*(n-1)}\),意思就是我先选第\(i\)个数(因为它肯定被交换嘛),然后再在其余中选一个,就是\(\frac{1}{n-1}\),然后因为顺序可以互换,所以要乘一个\(2\),所以最后式子就长上面那样了。

  • 之后我们发现,这样做是\(O(nk)\)的.

  • 考虑优化,就要考虑化简.

  • 其实发现,因为始终都是一些数在换来换去,所以我们可以先假设第\(i\)个数上一开始的位置是\(a_i\),并且一开始概率为\(1\).

  • 然后进行一轮交换之后,仍为\(a_i\)的概率,其实就是上面那坨式子.

  • 然后最后,不为\(a_i\)的概率乘上其他数的和再除以一个\(n-1\),就是期望了.

  • 很好理解吧~

  • 注意,要开long long!!!

#include <iostream>
#include <cstdio>
#include <cstring>

#define F(i, a, b) for (int i = a; i <= b; i ++)

using namespace std;

const int N = 1e6 + 10;

char ch[N]; long long k, len;
long double a[N], s[N], sum, ans;

int main() {
    freopen("data.in", "r", stdin); 
    scanf("%s %lld", ch + 1, &k), len = strlen(ch + 1);
    F(i, 1, len) a[i] = ch[i] - '0', sum += a[i];
    long double T = 1;
    F(i, 1, k)
        T = T * (len - 2) * 1.0 / len + (1 - T) * 2 / ((len - 1) * len);
    F(i, 1, len)
        ans = (long double) ans + ((1.0 * T * a[i] + (1.0 - T) * (sum - a[i]) / (len - 1.0)) * (1.0 * i * (len - i + 1)) / (1.0 * len * (len + 1) / 2.0));
    printf("%.13Lf", ans);
}

猜你喜欢

转载自www.cnblogs.com/Pro-king/p/9383468.html