http://acm.hdu.edu.cn/showproblem.php?pid=6034
基本的想法是统计出每个字母的贡献,然后贡献最小的就把更小的数字分给他
但这题关键在于贡献太大了,需要取模,又无法比较大小
所以我们想到因为只有26个字母,我们可以直接高精度算贡献,然后高精度比较大小,这题又是26进制的,那么我们高精度也搞26进制就行了,最后处理一遍进位
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxl=1e5+10;
const int mod=1e9+7;
int n,cas;ll ans;
int alen[30],idx[30],dy[30];
int a[30][maxl];
struct node
{
string s;
int id;
}b[30];
bool vis[30],in[30];
char s[maxl];
inline void prework()
{
for(int i=0;i<26;i++)
{
for(int j=0;j<=alen[i];j++)
a[i][j]=0;
alen[i]=0;vis[i]=false;in[i]=false;
}
int len,c,x;
for(int i=1;i<=n;i++)
{
scanf("%s",s+1);
len=strlen(s+1);
vis[s[1]-'a']=true;
for(int j=1;j<=len;j++)
{
c=s[j]-'a';
a[c][len-j+1]++;
alen[c]=max(alen[c],len-j+1);
}
}
for(int i=0;i<26;i++)
{
b[i].id=i;
for(int j=1;j<=alen[i];j++)
{
a[i][j+1]+=a[i][j]/26;
a[i][j]%=26;
if(a[i][j+1]>0)
alen[i]=max(alen[i],j+1);
}
}
}
inline bool cmp(const int &x,const int &y)
{
if(alen[x]!=alen[y])
return alen[x]<alen[y];
for(int i=alen[x];i>=1;i--)
if(a[x][i]!=a[y][i])
return a[x][i]<a[y][i];
return x<y;
}
inline void mainwork()
{
for(int i=0;i<26;i++)
idx[i]=i;
sort(idx,idx+26,cmp);
for(int i=0;i<26;i++)
if(!vis[idx[i]])
{
dy[idx[i]]=0,in[idx[i]]=true;
break;
}
for(int i=1;i<26;i++)
for(int j=0;j<26;j++)
if(!in[idx[j]])
{
dy[idx[j]]=i,in[idx[j]]=true;
break;
}
ll mi;ans=0;
for(int i=0;i<26;i++)
{
mi=1;
for(int j=1;j<=alen[i];j++)
{
ans=(ans+mi*dy[i]%mod*a[i][j]%mod)%mod;
mi=mi*26%mod;
}
}
}
inline void print()
{
++cas;
printf("Case #%d: %lld\n",cas,ans);
}
int main()
{
while(~scanf("%d",&n))
{
prework();
mainwork();
print();
}
return 0;
}