数学规律题,很容易计算的。以初始测试数据3为例。
Str Y I S V O W E L
--------------------------
Len 1 2 3 4 | 5 6 7 8
Y + | +
I + + | + +
S
V
O + + + + | + + + +
W
E + | +
L
首先注意1-4与5-8是对称的(仅长度不同)。长度为2的总数可以在长度为1的总数的基础上累加计算(因为2-len-1的字符若为Vow则各递增1),长度为3的可以在长度为2的基础上累加计算。
故,首先求得cnt[]数组表示从1开始到位置n的Vow字符数目。然后遍历1-len/2的长度,求得结果,若len为奇数,则单独再计算一次(len+1)/2。
其实就是递推规律题目,O(n)时间复杂度。
/* 509E */
#include <iostream>
#include <string>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstring>
#include <climits>
#include <cctype>
using namespace std; #define isVow(ch) (ch=='I'||ch=='E'||ch=='A'||ch=='O'||ch=='U'||ch=='Y') const int maxn = 5e5+;
char s[maxn];
int cnt[maxn]; int main() {
int i, j, k;
int len;
__int64 sum;
int l, r, tmp;
double ans; #ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
#endif scanf("%s", s+);
memset(cnt, , sizeof(cnt));
for (i=; s[i]; ++i) {
if (isVow(s[i]))
cnt[i] = cnt[i-]+;
else
cnt[i] = cnt[i-];
}
len = i-;
ans = .;
sum = ;
l = ;
r = len;
for (i=, j=len; i<=len/; ++i, --j) {
sum += cnt[r] - cnt[l];
ans += 1.0*sum/i + 1.0*sum/j;
++l;
--r;
}
if (len & ) {
sum += cnt[r] - cnt[l];
ans += 1.0*sum/i;
}
printf("%.7lf\n", ans); #ifndef ONLINE_JUDGE
printf("%d\n", (int)clock());
#endif return ;
}