hdu 6034 Balala Power! (2017 Multi-University Training Contest

hdu 6034  Balala Power! (2017 Multi-University Training Contest

Problem Description
hdu 6034  Balala Power! (2017 Multi-University Training Contest

Talented Mr.Tang has 7.
 
Input
The input contains multiple test cases.

For each test case, the first line contains one positive integers )
 
Output
For each test case, output "Case #y denotes the answer of corresponding case.
 
Sample Input
1
a
2
aa
bb
3
a
ba
abc
 
Sample Output
Case #1: 25
Case #2: 1323
Case #3: 18221
 
/*
题意:给出只含有小写字母的字符串,分别与0-25相匹配,然后把字符串看成是26进制,求所有字符串转化后的总和
解析:记录字母出现在每个字符串的位置以及出现的总次数,按照其权值从大到小分配25,24,23,...
官方题解:每个字符对答案的贡献都可以看作一个26进制的数字,问题相当于要给这些贡献加一个0到25的权重使得答案最大。
最大的数匹配25,次大的数匹配24依次类推。
排序后这样依次贪心即可,唯一注意的是不能出现前导 0。
*/
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <map>
#include <cmath>
#include <cstring>
typedef long long LL;
const LL N = 100000 + 100;
const LL mod = 1000000007;
using namespace std;
struct ss {
    char sc;
    //str用于记录某个字符在个十百千...位置上分别出现的次数
    int str[N];
    int id;
    bool operator < (const ss &a)const
    {
        for(int i = 0; i < N; i++)
            if(str[i] != a.str[i])
                return str[i] > a.str[i];
        return str[N - 1] > a.str[N - 1];
    }
} num[30];
LL k[N] = {1};
void init()
{
    for(LL i = 1; i < N; i++)
        k[i] = (k[i - 1] * 26) % mod;
}
int main()
{
    int n, tim = 1;
    init();
    while(~scanf("%d%*c", &n)) {
        char s[N];
        int ma = 0;
        int tt[30];
        for(int i = 0; i < 26; i++) {
            tt[i] = 0;
            memset(num[i].str, 0, sizeof(num[i].str));
        }
        for(int i = 0; i < n; i++) {
            scanf("%s", s);
            int len = strlen(s);
            //记录不能为前导0的字母,若是只有一个字母,不算是前导0
            if(len > 1)
                tt[s[0] - 'a']++;
            for(int j = 0; j < len; j++) {
                num[s[j] - 'a'].str[len - 1 - j]++;
            }
        }
        int flag = 0;
        for(int i = 0; i < 26; i++) {
            num[i].sc = i + 'a';
            for(int j = 0; j < N; j++) {
                //26进制,所以满26进一
                num[i].str[j + 1] += num[i].str[j] / 26;
                num[i].str[j] = num[i].str[j] % 26 ;
            }
            int c;
            //交换前后位置,权值按照从大到小的顺序
            for(int j = 0; j < N / 2; j++) {
                c = num[i].str[j];
                num[i].str[j] = num[i].str[N - j - 1];
                num[i].str[N - 1 - j] = c;
            }
        }
        sort(num, num + 26);
        int i;
        //排除前导0
        for(i = 25; i >= 0; i--) {
            if(tt[num[i].sc - 'a'] == 0) {
                break;
            }
        }
        ss t;
        for(int j = 25; j >= 0 && j > i; j--) {
            t = num[i];
            num[i] = num[j];
            num[j] = t;
        }
        LL sum = 0;
        for(int i = 0; i < 26; i++) {
            for(int j = 0; j < N; j++) {
                if(num[i].str[j]) {
                    sum = (sum + ((25 - i) * num[i].str[j] % mod) * k[N - 1 - j]) % mod;
                }
            }
        }
        printf("Case #%d: %lld
", tim++, sum);
    }
    return 0;
}