题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6034
题意:给'a'到'z'重新安排顺序,使得在给出的n个字符串分别代表的26进制数和最大。
一开始'a'到'z'只起到占位作用,分别统计某个字符在某个位置出现的次数和这个位置代表的价值。之后对每个字符某个位置的和进行进位处理。按照每个26进制数的大小排序就行了。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 const LL mod = 1e9+7; 6 const int maxn = 100100; 7 char str[maxn]; 8 int n, sz; 9 LL w[maxn], cnt[maxn][26], tot[26]; 10 bool vis[26]; 11 int perm[26]; 12 13 bool cmp(int i, int j) { 14 for(int k = sz - 1; k >= 0; k--) { 15 if(cnt[k][i] != cnt[k][j]) { 16 return cnt[k][i] < cnt[k][j]; 17 } 18 } 19 return 0; 20 } 21 22 signed main() { 23 // freopen("in", "r", stdin); 24 int _ = 1, len; 25 w[0] = 1; 26 for(int i = 1; i < maxn; i++) w[i] = w[i-1] * 26LL % mod; 27 while(~scanf("%d", &n)) { 28 sz = 0; 29 for(int i = 0; i < 26; i++) perm[i] = i; 30 memset(vis, 0, sizeof(vis)); 31 memset(cnt, 0, sizeof(cnt)); 32 memset(tot, 0, sizeof(tot)); 33 for(int i = 0; i < n; i++) { 34 scanf("%s", str); 35 len = strlen(str); 36 if(len != 1) vis[str[0]-'a'] = 1; 37 sz = max(sz, len); 38 reverse(str, str+len); 39 for(int j = 0; j < len; j++) { 40 cnt[j][str[j]-'a']++; 41 tot[str[j]-'a'] += w[j]; 42 tot[str[j]-'a'] %= mod; 43 } 44 } 45 for(int i = 0; i < 26; i++) { 46 for(int j = 0; j < sz; j++) { 47 cnt[j+1][i] += cnt[j][i] / 26; 48 cnt[j][i] %= 26; 49 } 50 while(cnt[sz][i]) { 51 cnt[sz+1][i] += cnt[sz][i] / 26; 52 cnt[sz][i] %= 26; 53 sz++; 54 } 55 } 56 sort(perm, perm+26, cmp); 57 int pos = -1; 58 for(int i = 0; i < 26; i++) { 59 if(!vis[perm[i]]) { 60 pos = perm[i]; 61 break; 62 } 63 } 64 LL ret = 0; 65 int p = 25; 66 for(int i = 25; i >= 0; i--) { 67 if(pos == perm[i]) continue; 68 ret += (LL)p * tot[perm[i]] % mod; 69 ret %= mod; p--; 70 } 71 printf("Case #%d: %lld ", _++, ret); 72 } 73 return 0; 74 }