题目描述

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.


输入

The input contains multiple test cases.

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

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

输出

For each test case, output “Case #x: y” in one line (without quotes), where x indicates the case number starting from 1 and y denotes the answer of corresponding case.

样例输入




aa 
bb 


ba 
abc

样例输出

Case #1: 25 
Case #2: 1323 
Case #3: 18221

题目大意:

输入一个数n,接下来有n行字符串,只有从‘a’到‘z’,向这些字符随机赋值从0到25,每个数只能使用一次,开头字符不可为0。字符串为26进制,求n个字符串相加的最大值。每个字符对答案的贡献都可以看作一个 26 进制的数字,问题相当于要给这些贡献加一个 0 到 25 的权重使得答案最大。最大的数匹配 25,次大的数匹配 24,依次类推。排序后这样依次贪心即可,唯一注意的是不能出现前导 0。

c++

#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> using namespace std; typedef long long LL; // 用LL来替换long long const int N = 100020; const int Q = 1e9 + 7; int n , L; int num[26][N]; //sum一维下标存该字母减去‘a’的ASCLL码,也就是该字母元素 //二维数组下标存该字母元素的位置,数组里存该字母元素出现的个数 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)); 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数组排序,排序后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; }