[原创]codeforces 509E Pretty Song [递推]【杂类】

2017-01-11 01:41:15 Tabris_ 阅读数:293


博客爬取于2020-06-14 22:42:18
以下为正文

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


题目链接:http://codeforces.com/contest/509/problem/E
-----------------------------------------------------------------------------------------.
E. Pretty Song
time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
When Sasha was studying in the seventh grade, he started listening to music a lot. In order to evaluate which songs he likes more, he introduced the notion of the song’s prettiness. The title of the song is a word consisting of uppercase Latin letters. The prettiness of the song is the prettiness of its title.

Let’s define the simple prettiness of a word as the ratio of the number of vowels in the word to the number of all letters in the word.

Let’s define the prettiness of a word as the sum of simple prettiness of all the substrings of the word.

More formally, let’s define the function vowel© which is equal to 1, if c is a vowel, and to 0 otherwise. Let si be the i-th character of string s, and si…j be the substring of word s, staring at the i-th character and ending at the j-th character (sisi + 1… sj, i ≤ j).

Then the simple prettiness of s is defined by the formula:


The prettiness of s equals

Find the prettiness of the given song title.

We assume that the vowels are I, E, A, O, U, Y.

Input
The input contains a single string s (1 ≤ |s| ≤ 5·105) — the title of the song.

Output
Print the prettiness of the song with the absolute or relative error of at most 10 - 6.

Examples
input
IEAIAIO
output
28.0000000
input
BYOB
output
5.8333333
input
YISVOWEL
output
17.0500000
Note
In the first sample all letters are vowels. The simple prettiness of each substring is 1. The word of length 7 has 28 substrings. So, the prettiness of the song equals to 28.

-----------------------------------------------------------------------------------------.
题目大意:
就是求所有子串中元音字母占比的和

解题思路:
这种题很明显就是贡献求解 。
然后对于每一个位置我们考虑如下

s0s1s2s3...sn1s_0s_1s_2s_3...s_{n-1}
我们只要知道每一个元音字符中所有在的子串都有哪些就好了

对于每一个元音字符我们能够确定在这些区间范围内它贡献1.
$e.g. : _ s_i {[0,i],[0,i+1]…[0,n-1]},,{[1,i],[1,i+1]…[1,n-1]}......{[i,i],[i,i+1]…[i,n-1] } $

那么结果就是

1i+1i+1+...+1n1\frac{1}{i}+\frac{1}{i+1}+...+\frac{1}{n-1}
1i1+1i+11+...+1n11\frac{1}{i-1}+\frac{1}{i+1-1}+...+\frac{1}{n-1-1}

11+12+...+1i\frac{1}{1}+\frac{1}{2}+...+\frac{1}{i}

上面的可能看着不太清晰
换成这个看一下就清晰了
11+12+...+1leni+1\frac{1}{1}+\frac{1}{2}+...+\frac{1}{len-i+1}
——12+13+...+1leni+1+1\frac{1}{2}+\frac{1}{3}+...+\frac{1}{len-i+1+1}
—— ——13+14+...+1leni+1+2\frac{1}{3}+\frac{1}{4}+...+\frac{1}{len-i+1+2}
——————————————
—— —— ——1i+1i+1+...+1len\frac{1}{i}+\frac{1}{i+1}+...+\frac{1}{len}.
(总感觉上面那里写错了呢,,,,,)

我们发现这样是很有规律的
我们可以把这个想象成
j=1ni=1j1i\sum_{j=1}^{n}\sum_{i=1}^{j}{\frac{1}{i} }

通过预处理
我们就能在O(1)的时候计算每个位置的贡献了.
就是把上面的平行四边形部分和变成3个左下为直角的三角形部分和的差的形式.

=========================华丽的分割线==========================
AC之后在standing里面看到另一种做法,
这种做法其实也是求贡献,只不过是以长度做的贡献,
把长度为1 为2 为n 的计算出来再累加起来就是了,
(感觉这样的不是怎么好想。。。所以不要脸的贴过来)
以下盗用这个博客

用数组s来存储前缀和。即s[i]表示前i个字符中元音字母个数,这样可以方便统计区间[l,r]元音字母个数。设串总长为L
则有:
长度为1的子串中元音字母出现的个数之和为:ans[1]=s[L]
长度为2:ans[2]=ans[1]+s[L-1]-s[1]
长度为3:ans[3]=ans[2]+s[L-2]-s[2]
……
最后结果即为 ans[1]/1+ans[2]/2+ans[3]/3+……+ans[L]/L

附本题代码
--------------------------------------------.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//方法一
# include <bits/stdc++.h>
using namespace std;
const int N = 500000+5;
typedef long long int LL;
/***************************************/
double a[N];

bool check(char ch){
return (ch=='I'||ch=='E'||ch=='A'||ch=='O'||ch=='U'||ch=='Y');
}

int main(){
string str;
cin>>str;
int len = str.length();
double ans = 0.0,sum = 0.0;
a[0]=0.0;
for(int i=1;i<=len;i++){
sum+=1.0/i;
a[i]=a[i-1]+sum;
}
for(int i=0;i<len;i++){
if(check(str[i])){
ans+=a[len]-a[len-i-1]-a[i];
}
}
printf("%.9lf\n",ans);
return 0;
}