#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
/*
大数进制转换
给定n个字符串,如何给a-z赋值,使得给定字符串在26进制下的和最大
如果字符串超过两位,最高位不能为0
*/
typedef long long LL;
const int mod=1e9+7;
const int maxn=1e5+100;
int n;
int cnt[27][maxn];
char s[maxn];
bool vis[27];
int p[27];
int dig;
//对每个字母的值进行排序,排序对象为字母ID
bool cmp(int a,int b)
{
for(int j=dig; j>=0; j--)//大数的比较
{
if(cnt[a][j]!=cnt[b][j])
{
return cnt[a][j]<cnt[b][j];
}
}
return a<b;
}
LL solve()
{
for(int i=0; i<26; i++)//26进制大数加法
{
p[i]=i;
for(int j=0; j<dig; j++)
{
cnt[i][j+1]+=cnt[i][j]/26;
cnt[i][j]=cnt[i][j]%26;
}
}
sort(p,p+26,cmp);
int pos=-1;
//一定会存在一个字母可以取0
for(int i=0; i<26; i++)
{
if(vis[p[i]]==0)//寻找值最小,又可以取0的字母
{
pos=i;
break;
}
}
for(int i=pos; i>=1; i--)//将该字母移到最左边
{
swap(p[i],p[i-1]);
}
LL ans=0;
LL k=1;
for(int i=0; i<26; i++)//i为该字母表示的数字
{
k=1;
for(int j=0; j<=dig; j++)
{
ans=(ans+cnt[p[i]][j]*k%mod*i%mod)%mod;
k=k*26%mod;//该位相应的权值
}
}
return ans;
}
int main()
{
int kase=1;
while(~scanf("%d",&n))
{
memset(cnt,0,sizeof(cnt));
memset(vis,0,sizeof(vis));
memset(p,0,sizeof(p));
dig=-1;
for(int i=0; i<n; i++)
{
scanf("%s",s);
int len=strlen(s);
reverse(s,s+len);//逆置字符串
for(int j=0; j<len; j++)
{
int c=s[j]-'a';
cnt[c][j]++;//分别统计每个位置,不同字母数量
}
dig=max(dig,len);//保存最大高位
vis[s[len-1]-'a']=1;//标记在最高位出现过的字母
}
printf("Case #%d: %I64d\n",kase++,solve());
}
}
HDU6034 Balala Power!(大数进制转换)
最新推荐文章于 2019-04-08 10:03:38 发布