Fedor is an avid traveler. As a result of his hobby, he has gathered a big collection of postcards from all over the world. Each postcard has a unique picture on the front side and some fields for address information and text on the back side. During one of the parties at Fedor’s house, he decided to show all his of postcards to the guests. To achieve that, he wants to lay them all out on the table. Initially, all of his postcards are arranged in a single stack that Fedor is holding in his hands. Unfortunately, some of the postcards in that stack can be turned incorrectly — upside down. Ideally, Fedor would like all postcards on the table to lie with the picture on top, but looking at every postcard and turning it over individually can be very time-consuming. Instead, he came up with the following process:
1. Let n be the number of postcards remaining in the stack in his hands. Fedor chooses a random number k uniformly between 1 and n and takes top k postcards from the stack.
2. He looks at the topmost postcard among these k postcards. If it is oriented in the wrong way, he turns the whole stack of k postcards upside down together.
3. He then puts these k postcards on the table without any further rotations.
4. If there are still some postcards remaining in the stack in his hands, Fedor goes back to step 1.
Of course, after all the postcards are on the table, there might still be some that lie back side up. What is the expected number of such postcards?
Input
The input consists of a single line of “C” and “W” characters — i-th character corresponds to i-th postcard in the stack, counting from the top of the stack. “C” means that i-th postcard is oriented correctly in the initial stack, and “W” means that i-th postcard is oriented in the wrong way. The number of characters is between 1 and 106 inclusive.
Output
Output one real number — the expected number of incorrectly placed postcards on the table. The absolute or relative error should not exceed 10−9.
Examples
foreign.in foreign.out
CWCC 1.0
WWCWCCW 2.333333333333
题解1:
计算每个位置为首的概率乘上以该点为首对应期望 然后在都加起来即可,先预处理,求一下W C 对应的前缀和 和 前缀和的前缀和,在第i个位置若是C 那期望就是 (sumc2[n]-sumc2[i-1]-sumc1[i-1]*(len-i)) / (len-i)/该点为首的概率,很容易我们就会计算得到,第一个点概率为1,第二个为1/n,第三个为1/n+1/(n*(n-1)) = 1/(n-1),......依次类推
#include<iostream>
#include<cstdio>
using namespace std;
const int N=1e6+10;
double sumc1[N],sumc2[N];
double sumw1[N],sumw2[N];
int main()
{
freopen("foreign.in","r",stdin);
freopen("foreign.out","w",stdout);
string s;
cin>>s;
int len=s.size();
if(s[0]=='W') sumw1[0]=1,sumw2[0]=1;
else sumc1[0]=1,sumc2[0]=1;
for(int i=1;i<len;i++)
{
sumw1[i]=sumw1[i-1];
if(s[i]=='W') sumw1[i]+=1;
sumw2[i]+=sumw2[i-1]+sumw1[i];
sumc1[i]+=sumc1[i-1];
if(s[i]=='C') sumc1[i]+=1;
sumc2[i]+=sumc2[i-1]+sumc1[i];
}
double ans;
if(s[0]=='W')
ans=(double)sumc2[len-1]/len;
else
ans=(double)sumw2[len-1]/len;
for(int i=1;i<len;i++)
{
double p=(double)1/(len-i+1)/(len-i);
if(s[i]=='W')
ans+=(sumc2[len-1]-sumc2[i-1]-sumc1[i-1]*(len-i))*p;
else
ans+=(sumw2[len-1]-sumw2[i-1]-sumw1[i-1]*(len-i))*p;
}
printf("%.12f\n",ans);
return 0;
}
题解2:
无敌的佳神还有另一种思路,就是从后往前求 dp[i] 表示 从i开始到最后的期望,每次计算的S W ,就是 每个位置S W到最后的距离 累加起来就可以了, ans维护一个dp[i]的后缀和 +1太牛逼了 有哪路大神来把这位又可爱又聪明的+咦咦咦带走啊,咋了,你想? 这个题都不会做,你是没有机会的了,死心吧。
#include<iostream>
#include<cstdio>
using namespace std;
const int N=1e6+10;
double dp[N];
int main()
{
freopen("foreign.in","r",stdin);
freopen("foreign.out","w",stdout);
string s;
cin>>s;
int len=s.size();
double sc=0,sw=0,ans=0;
for(int i=len-1;i>=0;i--)
{
if(s[i]=='W')
{
dp[i]=(ans+sc)/(len-i);
sw+=(len-i);
}
else
{
dp[i]=(ans+sw)/(len-i);
sc+=(len-i);
}
ans+=dp[i];
}
printf("%.12f\n",dp[0]);
return 0;
}