您的位置:首页 > 其它

HDU 6034 Balala Power! 排序 贪心

2017-07-25 21:52 429 查看

链接

http://acm.hdu.edu.cn/showproblem.php?pid=6034

题意

给一组字符串,把每个字母变成[0,25]中的一个数(不准有两个字母变成的数相同),求这一组26进制数转换成10进制后的最大和(不准出现前缀0),模1e7

思路

简单的模拟题(写写这题蹭点访问量2333)

比赛的时候sjt看完这题想到了思路,觉得我比较适合写这种题(sjt,一个对此博客贡献巨大的神犇,我只是他的伟大思想的记录者,逃,2333,= =)

先标记出不能为0的数,那些在长度大于1的字符串开头的字母不能为0。

然后用数组计算每个字母的权值,复杂度O(26∗1e5),每个字母在某个位置,其对应的26进制数的某位就要多个1,用数组模拟这个数,然后从底位到高位把大于等于26的值进位,然后对这些数排序,显然直接排序划不来,我们用一个
cmp()
把每个字母当作指针特殊处理下这个操作。

最后先把可以为0的数中权值最小的数标记为0,然后按权值从大到小决定每个字符的取值。

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

#define MS(x, y) memset(x, y, sizeof(x));

typedef long long LL;
const int MAXN = 1e5 + 5;
const int MOD = 1e9 + 7;

int n;
int head[MAXN], tail[MAXN];
int val[26];
int weights[26][MAXN], mx_len[26];
int arr[30];
char str[1000005];

bool cmp(int a, int b) {
if (mx_len[a] != mx_len[b]) return mx_len[a] < mx_len[b];
for (int i = mx_len[a]; i >= 0; --i) {
if (weights[a][i] != weights[b][i]) return weights[a][i] < weights[b][i];
}
return false;
}

int main() {
int kase = 0;
while (~scanf("%d", &n)) {
MS(val, -1);
MS(mx_len, 0);
for (int i = 0; i < 26; ++i) weights[i][0] = 0;
for (int i = 1; i <= n; ++i) {
head[i] = tail[i - 1];
scanf("%s", str + head[i]);
tail[i] = head[i] + strlen(str + head[i]);
// 标记出不能为0的数
if (tail[i] - head[i] > 1) val[str[head[i]] - 'a'] = 1;
for (int j = tail[i] - 1, k = 0; j >= head[i]; --j, ++k) {
if (k > mx_len[str[j] - 'a']) {
mx_len[str[j] - 'a'] = k;
weights[str[j] - 'a'][k] = 0;
}
++weights[str[j] - 'a'][k];
}
}
//    cout << str << endl;
for (int i = 0; i < 26; ++i) {
for (int j = 0; j <= mx_len[i]; ++j) {
if (weights[i][j] >= 26) {
if (j + 1 > mx_len[i]) {
mx_len[i] = j + 1;
}
weights[i][j + 1] += weights[i][j] / 26;
weights[i][j] %= 26;
}
}
}
for (int i = 0; i < 26; ++i) arr[i] = i;
sort(arr, arr + 26, cmp);
// 先决定哪个字母为0
for (int i = 0; i < 26; ++i) if (val[arr[i]] == -1) {
val[arr[i]] = 0;
break;
}
// 接着按权值决定每个字符的取值
int cnt = 25;
for (int i = 25; i >= 0; --i) if (val[arr[i]] != 0) val[arr[i]] = cnt--;
LL ans = 0, tmp;
for (int i = 1; i <= n; ++i) {
tmp = 0;
for (int j = head[i]; j < tail[i]; ++j) {
(tmp *= 26) %= MOD;
(tmp += val[str[j] - 'a']) %= MOD;
}
(ans += tmp) %= MOD;
}
printf("Case #%d: %I64d\n", ++kase, ans);
// 最后一步清空,怕memset太慢了
for (int i = 0; i < 26; ++i) for (int j = 0; j <= mx_len[i]; ++j) weights[i][j] = 0;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐