贪心

HDU 6034 Balala Power!

Posted on

多校第一场的恶心题……因为前几天补题数量太多,博客一直没写,现在补上……

这道题我整整写了一个下午+晚上,mmp,一方面是题目本身恶心,另一方面也反映了我的脑子问题。

题意:
给你指定数量的小写字符串,让你把字母,转化成数字,也就是说 a-z 各自对应 0-25。要求所得数字和最大。
同时转化出的数字不能出现前导零。

思路:
将每个字符的贡献转化成一个25进制的数,用一个 26× 1e5 的数组存储,将其进行排升序。
再是考虑前导零的情况,反向遍历找到第一个不存在前导零的数字标记一下即可。

AC Code

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
const int mod = 1e9 + 7;

int n, len, max_len;
char buf[maxn];
ll mul[maxn];
bool lead[30];
int a[30];

struct ch {
    int num[maxn];
    int pos;
    void init(int id)
    {
        pos = id;
        memset(num, 0, sizeof num);
    }
    bool operator<(const ch& a) const
    {
        for (int i = max_len - 1; i >= 0; i--) {
            if (num[i] != a.num[i])
                return num[i] < a.num[i];
        }
        return false;
    }
} key[27];

int change(char sen[])
{
    int len = strlen(sen);
    for (int i = 0; i < len / 2; ++i) {
        char ch = sen[i];
        sen[i] = sen[len - i - 1];
        sen[len - i - 1] = ch;
    }
    return len;
}

int main()
{
    mul[0] = 1;
    for (int i = 1; i < maxn; i++)
        mul[i] = mul[i - 1] * 26 % mod;
    int cas = 0;
    while (scanf("%d", &n) != EOF) {
        for (int i = 0; i < 26; i++)
            key[i].init(i), lead[i] = false;
        max_len = 0;
        while (n--) {
            scanf("%s", buf);
            len = change(buf);
            if (len > 1)
                lead[buf[len-1] - 'a'] = true;
            max_len = max(max_len, len);
            for (int i = 0; i < len; ++i)
                key[buf[i] - 'a'].num[i]++;
        }
        for (int i = 0; i < 26; ++i) {
            for (int j = 0; j < max_len; ++j) {
                key[i].num[j + 1] += key[i].num[j] / 26;
                key[i].num[j] %= 26;
            }
            while (key[i].num[max_len] > 0) {
                key[i].num[max_len + 1] += key[i].num[max_len] / 26;
                key[i].num[max_len++] %= 26;
            }
        }
        sort(key, key + 26);
        int zero = -1;
        for (int i = 0; i < 26; ++i)
            if (!lead[key[i].pos]) {
                zero = key[i].pos;
                break;
            }
        ll res = 0, x = 25;
        for (int i = 25; i >= 0; --i) {
            if (key[i].pos != zero) {
                for (int j = 0; j < maxn; j++)
                    res = (res + x * key[i].num[j] * mul[j] % mod) % mod;
                x--;
            }
        }
        printf("Case #%d: %lld\n", ++cas, res);
    }
    return 0;
}