HDU6304(Balala Power!)
阿新 • • 發佈:2019-01-27
把所有的字串用 26 的多項式表示,所有字串的和就是多項式相加,按照字母提取公因式,整理成26進位制,作為字母的係數,按照係數給字母排序,係數越大的字母分配的權值越大。
關於前導零的處理,可以在排完序之後,從不是首字母的字母中選出排名最靠後的那一個,記錄為0,最後分配權值和累加答案的時候跳過。
#include <iostream> #include <cstdio> #include <algorithm> #include <string.h> #include <stdlib.h> #include <set> #include <algorithm> using namespace std; typedef long long unsigned int ull; typedef long long ll; const int maxL = 100000 + 10; const ull mod = 1e9 + 7; int f[27][maxL]; ull expp[maxL]; char S[maxL]; bool first[26]; int a[26]; ull w[26]; int n; void init(){ expp[0] = 1; for (int i=1; i<maxL; i++){ expp[i] = expp[i-1] * 26; expp[i] %= mod; } } int cmp(int a, int b){ if (f[a][0] != f[b][0]) return f[a][0] > f[b][0]; for (int i=f[a][0]; i>=1; i--){ if (f[a][i] != f[b][i]) return f[a][i] > f[b][i]; } return 0; } int main() { init(); int t = 0; while (~scanf("%d", &n)){ t++; memset(f, 0, sizeof(f)); memset(first, false, sizeof(first)); memset(w, 0, sizeof(w)); for (int i=0; i<n; i++){ scanf("%s", S); first[S[0] - 'a'] = true; int len = strlen(S); reverse(S, S+len); for (int j=0; j<len; j++){ int k = S[j] - 'a'; f[k][j+1]++; if (j+1 > f[k][0]) f[k][0] = j+1; w[k] = (w[k] + expp[j]) % mod; } } for (int i=0; i<26; i++){ for (int j=1; j<=f[i][0]; j++){ f[i][j+1] += f[i][j] / 26; f[i][j] %= 26; } int len = f[i][0]; while (f[i][len] > 0){ f[i][len+1] += f[i][len] / 26; f[i][len] %= 26; len++; } f[i][0] = len; } for (int i=0; i<26; i++) a[i] = i; sort(a, a+26, cmp); int zero = 0;//記錄權值為 0 的字母 for (int i=25; i>=0; i--){ if (!first[a[i]]){ zero = a[i]; break; } } ull ans = 0; int x = 25; for (int i=0; i<26; i++){ if (zero == a[i]) continue; ans += (w[a[i]] * (ull)(x--)) % mod; //這裡不要用(26-i-1),因為可能會跳過權值為0的字母 ans %= mod; } cout << "Case #" << t << ": " << ans << endl; } return 0; }