题目链接:http://codeforces.com/problemset/problem/509/E
题意:给你一个字符串,求字串中包括子串中I, E, A, O, U, Y.所占的概率和。
题解:有些技巧的题目,关于概率之和可以考虑每个点单独处理然后最终求和。
假设i点是I, E, A, O, U, Y中的一个。
以i为终点的概率之和。(字符串从1开始)
1+1/2+1/3+....1/i=sum[i];
以i为起点不包括i单点的情况。
1/2+1/3+....1/(len-i+1)=sum[len-i+1]-sum[1];
以i为中间点分类讨论。
字符串中i的位置为2时。
1/3+1/4+1/5+....1/(len-i+2)=sum[len-i+2]-sum[2];
位置为3时
1/3+1/4+1/5+....1/(len-i+3)=sum[len-i+3]-sum[3];
....
位置为i时
1/(i+1)+1/(i+2)+....1/len=sum[len]-sum[i];
最后全部加起来
sum[len]+sum[len-1]+...sum[len-i+1]-(sum[i]+s[i-1]+....sum[1])=tot[len]-tot[len-i]-tot[i];
(tot表示前缀和的前缀和)
#include <iostream> #include <cstring> #include <string> using namespace std; const int M = 5e5 + 10; char s[M]; double sum[M] , tot[M]; int main() { sum[0] = 0.0; for(int i = 1 ; i < M ; i++) { sum[i] = 1.0 / i + sum[i - 1]; } tot[0] = 0.0; for(int i = 1 ; i < M ; i++) { tot[i] = sum[i] + tot[i - 1]; } scanf("%s" , s + 1); int len = strlen(s + 1); double ans = 0; for(int i = 1 ; i <= len ; i++) { if(s[i] == 'A' || s[i] == 'E' || s[i] == 'I' || s[i] == 'O' || s[i] == 'U' || s[i] == 'Y') { ans += sum[i]; ans += tot[len] - tot[len - i] - tot[i]; } } printf("%.7lf " , ans); return 0; }