Codeforces 509E Pretty Song (思维)
E. Pretty Song
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(c) 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.
The input contains a single string s (1 ≤ |s| ≤ 5·105) — the title of the song.
Print the prettiness of the song with the absolute or relative error of at most 10 - 6.
IEAIAIO
28.0000000
BYOB
5.8333333
YISVOWEL
17.0500000
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.
一开始完全没有思路……但是后来想着想着就出来一个O(N)的。要用到预处理。(假设字符串长度为N) 首先把那些元音字母的位置筛出来。
我的代码中的ai表示(1/1+1/N) + (2/2+2/(N-1)) + ... + (i/i+i/(N-i+1)) bi表示1/1+1/2+1/3+...+1/i (之后我会解释为什么要这样预处理)
每次对于一个元音字母的位置x,无论他在该字符串的前一半还是字符串的后一半,都把他调到前一半的对称位置。(比如说输入的字符串长度为6,我现在要处理的元音字母的位置为5,那么就可以等效成2),然后利用等效之后的这个x生成一个序列,这个序列是分数,长度为N,其中分母为1,2,3,4,...,N,分子为1,2,3,....,x-1,x,x,x,x-1,...,3,2,1(对就是这样的一个序列现在我们要计算这个序列的和),就利用之前预处理出来的a数组和b数组,在O(1)内就可以实现,然后把每次得到的这个和累加起来,结果就是答案。
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define REP(i,n) for(int i(0); i < (n); ++i) 6 #define rep(i,a,b) for(int i(a); i <= (b); ++i) 7 #define dec(i,a,b) for(int i(a); i >= (b); --i) 8 #define for_edge(i,x) for(int i = H[x]; i; i = X[i]) 9 10 const int N = 600000 + 10; 11 const int M = 10000 + 10; 12 const int Q = 1000 + 10; 13 const int A = 30 + 1; 14 15 char s[N]; 16 int len, cnt; 17 int c[N]; 18 double a[N], b[N]; 19 int l, r; 20 double ans; 21 int x; 22 23 int main(){ 24 25 scanf("%s", s + 1); 26 len = strlen(s + 1); cnt = 0; 27 28 l = 0; r = len + 1; 29 a[0] = b[0] = 0; 30 rep(i, 1, len) b[i] = b[i - 1] + (double)1 / (double)i; 31 32 if (len & 1){ 33 rep(i, 1, len >> 1){ 34 ++l, --r; 35 a[i] = a[i - 1] + i / (double)l + i / (double)r; 36 } 37 a[len / 2 + 1] = a[len / 2] + (++l) / (len / 2 + 1); 38 } 39 else{ 40 rep(i, 1, len >> 1){ 41 ++l, --r; 42 a[i] = a[i - 1] + i / (double)l + i / (double)r; 43 } 44 } 45 46 47 48 49 rep(i, 1, len){ 50 if (s[i] == 'A' || s[i] == 'E' || s[i] == 'I' || s[i] == 'O' || s[i] == 'U' || s[i] == 'Y'){ 51 c[++cnt] = i; 52 } 53 } 54 55 ans = 0; 56 rep(i, 1, cnt){ 57 x = c[i]; 58 if (x > len / 2) x = len - x + 1; 59 if (x <= len / 2) ans += a[x] + (b[len - x] - b[x]) * x; 60 else ans += a[x]; 61 } 62 63 printf("%.7f\n", ans); 64 65 66 return 0; 67 68 }