题意:
- 对于一叠 n 张卡片,每次随机取前 k 张
- 若取到的 k 张的第一张为 W ,则 k 张卡片的状态全部翻转放置桌上。
- 若一叠卡片仍有剩余,则继续上述操作
问最后桌面上为 W 的卡片的期望?
解题思路:
假设一个串为S,S_i表示前后i位,E(s)为串s的期望,len为字符串长度,Wi为前i为中w的个数,那么期望为 ∑ i = 1 n ( 1 / l e n ) ∗ ( w i + E ( S ( n − i ) ) ) \sum_{i=1}^n(1/len)*(w_i+E(S_(n-i))) i=1∑n(1/len)∗(wi+E(S(n−i)))
那么假设知道了E(S_i),和 S U M = ∑ j = i n E ( S i ) SUM=\sum_{j=i}^nE(S_i) SUM=j=i∑nE(Si) 那么可求E(S_(i+1))
- 新加上的第一位是W,第一位是W那么第一次取得k位中C和W互换,那么E(S_(i+1))就等于第一步取1位,取两位…到取全长的时候C的数量和加上SUM
,每种等概率,再乘上1/len就是ans了 - 新加上的第一位是C,第一位是C,串不变,那么E(S_(i+1))就等于第一步取1位,取两位…到取全长的时W的数量和加上SUM,每种等概率,再乘上1/len就是ans了
代码:
#include<iostream>
#include<cstring>
#include<string>
#include<vector>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
using namespace std;
typedef long long ll;
typedef pair<ll,ll>pii;
typedef vector<int>vi;
#define rep(i,a,b) for(int i=(a);i<(b);i++)
#define fi first
#define se second
#define de(x) cout<<#x<<"="<<x<<endl
#define per(i,a,b) for(int i=(b)-1;i>=(a);--i)
const int N=1e5+5;
string s;
int main()
{
freopen("foreign.in", "r", stdin);
freopen("foreign.out", "w", stdout);
cin>>s;
int len=s.size();
ll c=0,w=0; //c,w分别计算第一步取1位....取全长所有情况得C,W之和,
double ans=0; //计算第i位期望
double sum=0; //后i位得期望和
per(i,0,len){
if(s[i]=='C'){
c+=len-i; //在第n-i位 那么在所有情况中(第一步取1位....取全长)就会被加上n-i次
ans=(sum+w)/(len-i);
sum+=ans;
}
else{
w+=len-i;
ans=(sum+c)/(len-i);
sum+=ans;
}
}
printf("%0.10lf",ans);
return 0;
}