codeforces 509 E. Pretty Song(前缀和+前缀和的前缀和)

题目链接: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;
}
原文地址:https://www.cnblogs.com/TnT2333333/p/6839622.html