HDOJ多校 6034- Balala Power!

来源:互联网 发布:解放军报网络投稿方式 编辑:程序博客网 时间:2024/06/06 10:54

Balala Power!

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 3502    Accepted Submission(s): 827


Problem Description

Talented Mr.Tang has n strings consisting of only lower case characters. He wants to charge them with Balala Power (he could change each character ranged from a to z into each number ranged from 0 to 25, but each two different characters should not be changed into the same number) so that he could calculate the sum of these strings as integers in base 26 hilariously.

Mr.Tang wants you to maximize the summation. Notice that no string in this problem could have leading zeros except for string "0". It is guaranteed that at least one character does not appear at the beginning of any string.

The summation may be quite large, so you should output it in modulo 109+7.
 

Input
The input contains multiple test cases.

For each test case, the first line contains one positive integers n, the number of strings. (1n100000)

Each of the next n lines contains a string si consisting of only lower case letters. (1|si|100000,|si|106)
 

Output
For each test case, output "Case #xy" in one line (without quotes), where x indicates the case number starting from 1 and 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

题目链接:Balala Power


题目意思:有 n 个小写的字符串,想要把它们变为 26 进制的 0-25 的数字,问 n 个字符串最大的和为多少?还有,不能有前导0,除非就是给你一个字母,然后输入n行字符串,每个字母都对应一个数字,从0到25,因为不确定哪个字母对应哪个数字,所以我们得求出最优的字母赋予最大的值


 
#include <bits/stdc++.h>using namespace std;typedef long long LL;const int N = 100020;const int Q = 1e9 + 7;int n , L;int num[26][N];//sum一维下标存该字母减去‘a’的ASCLL码,也就是该字母元素//sun二维数组下标存该字母元素的位置,数组里存该字母元素出现的个数int power[N] , sum[N];//power数组存对应位的权值,sum数组存相同字母对应位的权值总和bool ban[26];//作为标记数组,将出现的字母作标记char str[N];int a[26];//用来映射每个字母所代表的值bool cmp(int A , int B)//排序依据是num存的字母从高位到低位个数的多少{    for (int i = L - 1 ; i >= 0 ; -- i)    {        if (num[A][i] != num[B][i])        {            return num[A][i] < num[B][i];        }    }    return 0;}void work() {    memset(num , 0 , sizeof(num));//将数组都初始化为0    memset(ban , 0 , sizeof(ban));    memset(sum , 0 , sizeof(sum));    L = 0;    for (int i = 0 ; i < n ; ++ i)    {        scanf("%s" , str);        int len = strlen(str);        if (len > 1)//如果字符串长度大于1,则标记该字符串首字母不能为0        {            ban[str[0] - 'a'] = 1;        }        reverse(str , str + len);//将字符串str倒置        for (int j = 0 ; j < len ; ++ j)        {            ++ num[str[j] - 'a'][j];//存字母出现的次数            sum[str[j] - 'a'] += power[j];//求出现的字母的所有权值            if (sum[str[j] - 'a'] >= Q) //如果sum里的数超过了Q,则对它取余            {                sum[str[j] - 'a'] -= Q;            }        }        L = max(L , len);//保存输入字符串的最大长度    }    for (int i = 0 ; i < 26 ; ++ i)    {        for (int j = 0 ; j < L ; ++ j)        {            //处理元素i个数的进位情况            num[i][j + 1] += num[i][j] / 26;            num[i][j] %= 26;        }        while (num[i][L])        {            num[i][L + 1] += num[i][L] / 26;            num[i][L ++] %= 26;        }        a[i] = i;//a数组里存的是字母,下标是对应的值    }    sort(a , a + 26 , cmp);//对a数组排序    int zero = -1;    for (int i = 0 ; i < 26 ; ++ i )    {        if (!ban[a[i]])//找到最小可以为0的值        {            zero = a[i];            break;        }    }    int res = 0 , x = 25;    for (int i = 25 ; i >= 0 ; -- i)    {        if (a[i] != zero)//如果不是单个字母就开始统计所有的加和值        {            res += (LL)(x --) * sum[a[i]] % Q;            res %= Q;        }    }    static int ca = 0;    printf("Case #%d: %d\n" , ++ ca , res); }int main() {    power[0] = 1;//初始化power数组,个位的权值为26^0=1    for (int i = 1 ; i < N ; ++ i) {            //依次用低一位的权值*26得到高一位的权值,然后对10^9+7取模        power[i] = (LL)power[i - 1] * 26 % Q;    }    while (~scanf("%d" , &n)) {        work();    }    return 0;}