Balala Power!
时间限制: 4 Sec 内存限制: 128 MB题目描述
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.
输入
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)
输出
样例输入
1
a
2
aa
bb
3
a
ba
abc
样例输出
Case #1: 25
Case #2: 1323
Case #3: 18221
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
#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]; ///num[字母][该字母在的位数]=字母在该位出现的次数 int power[N], sum[N]; ///sum[字母]=该字母目前的贡献,pow[位数]=该位的贡献(26^x); bool ban[ 26]; ///处理前导零 char str[N]; int a[ 26]; ///根据在每位出现的次数进行排序,因为位数高的占的权重比较大, ///所以先从高位开始,按权重从小到大排序 bool cmp( int A, int B) { 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) { ban[str[ 0] - 'a'] = 1; ///如果该字母在第一位,则ban[**]=1; } reverse(str, str + len); ///倒置数组 for ( int j = 0 ; j < len ; ++ j) { ++ num[str[j] - 'a'][j]; ///该字母在j位出现的次数加一 sum[str[j] - 'a'] += power[j]; ///该字母的贡献增加 if (sum[str[j] - 'a'] >= Q) sum[str[j] - 'a'] = sum[str[j] - 'a']%Q; } L = max(L, len); } ///对每个字母出现的次数进行进位处理,(以26进制) for ( int i = 0 ; i < 26 ; ++ i) { for ( int j = 0 ; j < L ; ++ j) { 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; } ///排序 sort(a, a + 26, cmp); int zero = - 1; for ( int i = 0 ; i < 26 ; ++ i) { ///找出贡献比较小,不在第一位的(可以为零),给它赋值为零,使最后结果最大 if (!ban[a[i]]) { 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; for ( int i = 1 ; i < N ; ++ i) { power[i] = (LL)power[i - 1] * 26 % Q; ///power[i]=26^i; } while (~scanf( "%d", &n)) { work(); } return 0; } |