字符串的字典序可以看作为26进制数字的大小
坑点:大数比较大小需要注意
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef int lint;
const lint maxn = 1000020;
const LL mod = 1e9+7;
char str[maxn];
lint ch[26][maxn];
lint mmlen;
void add( lint n,lint p ){
while(1){
ch[n][p]++;
mmlen = max(mmlen,p);
if(ch[n][p] >= 26){
ch[n][p] -= 26;p++;
continue;
}
else break;
}
}
vector<lint> ve;
LL mypow[maxn];
void prework(){
for(lint i = 0; i< 26;i++) ve.push_back(i);
mypow[0] = 1;
for(lint i = 1;i <maxn;i++) mypow[i] = mypow[i-1]*26%mod;
}
bool cmp(const lint a,const lint b){
for( lint i = mmlen;i >= 0;i-- ){
if( ch[a][i] < ch[b][i] ) return true;
else if( ch[a][i] > ch[b][i] ) return false;
}
return false;
}
lint used[30],flag[30],res[30];
void init(){
memset(flag,0,sizeof(flag));
memset(ch,0,sizeof(ch));
memset(used,0,sizeof(used));
memset(res,0,sizeof(res));
}
LL cal(){
LL ans = 0;
for( lint i = 0;i < 26;i++ ){
for( lint j = 0;j <= mmlen;j++ ){
ans = (ans + (LL)res[i]*mypow[j]%mod*ch[i][j]%mod)%mod;
}
}
return ans;
}
int main(){
prework();
lint n,ccnt;
lint ca = 0;
while( 1 == scanf("%d",&n) ){
printf("Case #%d: ",++ca);
init();
mmlen = 0;ccnt = 0;
for( lint i = 0 ;i < n;i++ ){
scanf("%s",str);
lint len = strlen(str);
if(len!= 1){
flag[str[0]-'a'] = 1;
}
for( lint j = 0;j < len;j++ ){
add( str[j]-'a',len-j-1 );
if(!used[str[j]-'a'])ccnt++;
used[str[j]-'a'] = 1;
}
mmlen = max(mmlen,len);
}
mmlen++;
sort(ve.begin(),ve.end(),cmp);
lint flag2;
if(ccnt == 26){
for( lint i = 0;i < 26;i++ ){
if(flag[ve[i]]) continue;
flag2 = ve[i];
break;
}
}
lint cur = 25;
for( lint i = ve.size()-1;i >= 0;i-- ){
if(ccnt == 26 && flag2 == ve[i]) continue;
res[ ve[i] ] = cur--;
}
LL ans = cal();
printf("%I64d\n",ans);
}
return 0;
}