TheSwaps

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/SSL_Yyx/article/details/81105148

题目

Description

Alice得到了一个整数, 她将其视作长度为n的字符串S。为了好玩,她进行了k次如下操作:

1) 随机选取两个不同的位置x和y(即每次操作, {< x, y> | 1<=x < y <=n}中每个元素都有相同的概率被选到)

2) 交换数位S[x]和数位S[y]

为了自虐,在Alice恶搞之后,Bob会随机一个子串(即对于任意子串都有相同概率被选到),然后他想知道他选出的子串中各个位置数字之和的期望为多少。聪明的Bob想出了一个很好的方法来解决这个问题,那就是把这个问题交给你。Bob会告诉你S和k,你需要告诉他期望。

Input

一行,包含字S和k。

Output

一行,一个实数。当你的输出和标准答案的差距少于10^-6时,被认为是正确的。

Sample Input

输入1:

477 1

输入2:

57268508514909598902647806463326698034850446919720257361969 7

Sample Output

输出1:

10

输出2:

98.3238536775161

分析

swap:k次交换后,ANS=每一位的期望值*每一位被选出的概率。

显然第i位被选出的概率=包含i的子串数/总子串数=i*(n-i+1)/(n*(n+1)/2)。

那如何求k次交换后每一位的期望值?

我们假设最初第i位为ai,p次交换后第i位仍然等于ai的概率是x,

那么p+1交换后第i为仍然等于ai的概率是x*(1-(n-1)/q))+(1-x)/q,

其中q=n*(n-1)/2。接下来有一个性质:如果第i位不为ai,

那么第i位是a中其他任何数的概率都是一样的(交换的随机性决定的)。

因此如果k次交换后,第i位为ai的概率是x,

那么第i位的期望值=ai*x+(sum-ai)/(n-1)*(1-x)。

至此问题就可以解决了。QAQ

程序

#include<cstdio>
using namespace std;
    double a[1000001],ans,s,sum;
    int n,k;
    char ch;
int main(){
    while(ch=getchar(),ch>='0'&&ch<='9') 
        sum+=(a[++n]=ch-'0');
    scanf("%d",&k);
    s=1;
    for(int i=1;i<=k;i++) 
        s=s*(1.0-(n-1.0)/(n*(n-1.0)/2.0))+(1.0-s)/(n*(n-1.0)/2.0);
    for(int i=1;i<=n;i++)
        ans+=(i*(n-i+1.0)/(n*(n+1.0)/2.0))*(a[i]*s+(sum-a[i])/(n-1.0)*(1.0-s));
    printf("%.7lf\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/SSL_Yyx/article/details/81105148