/*
细心:马虎,数据少开了10倍,T了4小时- -
题意;给你一堆a-z的字符串,a-z的权值自己定,要求最后所有字符串的总和最大,按26进制展开。
很显然要统计每个字母的出现次数 —>与位置有关,
那利用数组储存次数,根据关系,表现成26进制。
再利用队列优化储存数组,提升速度 249ms.
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define ms(a,b) memset(a,b,sizeof(a))
typedef long long ll;
const int Size =666;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
const double eps=1e-10;
char str[100005];
ll fac[100005]={1};
int st[26][100005];
int vt[26][100005];
int top[26];
int n1[27][100005];
int tag[27];
int cmp(int a,int b)
{
int p1=a,p2=b;
for(int i=1;i<=top[p1]&&i<=top[p2];i++)
{
if(vt[p1][i]!=vt[p2][i]) return vt[p1][i]>vt[p2][i];
if(st[p1][i]!=st[p2][i]) return st[p1][i]>st[p2][i];
}
return top[p1]>top[p2];
}
int vis[27];
int main()
{
int t,cas=0;
for(int i=1;i<=100002;i++)
{
fac[i]=(fac[i-1]*26)%mod;
}
while(~scanf("%d",&t))
{memset(n1,0,sizeof(n1));
int ml=0;
for(int i=0;i<26;i++)
{
tag[i]=i;
top[i]=0;
vis[i]=0;
}
while(t--)
{
scanf("%s",str);
int len=strlen(str);
if(len>1) vis[str[0]-'a']=1;
ml=max(ml,len);
for(int i=0;i<len;i++)
{
n1[str[i]-'a'][len-i]++;
}
}
for(int i=0;i<=25;i++)
{
for(int j=1;j<=ml+1;j++)
{
n1[i][j+1] +=n1[i][j]/26;
n1[i][j] %=26;
}
}
for(int i=0;i<=25;i++)
{
for(int j=ml+2;j>=1;j--)
{
if(n1[i][j])
{
st[i][++top[i]]=n1[i][j];
vt[i][top[i]]=j;
}
}
}
sort(tag,tag+26,cmp);
int cnt=25;
while(vis[tag[cnt]]) cnt--;
int tagv=tag[cnt];
for(int i=cnt;i<26;i++)
{
if(i<=24) tag[i]=tag[i+1];
else tag[i]=tagv;
}
ll ans=0;
for(int i=0;i<26;i++)
{
int pos=tag[i];
if(top[pos])
{
ll sum=0;
for(int j=1;j<=top[pos];j++)
{
sum=(sum+((25-i)*(fac[vt[pos][j]-1]*st[pos][j]%mod)%mod))%mod;
}
ans =(ans+sum)%mod;
}
}
printf("Case #%d: %d\n",++cas,ans);
}
return 0;
}
07-13
07-13
07-13
“相关推荐”对你有帮助么?
-
非常没帮助
-
没帮助
-
一般
-
有帮助
-
非常有帮助
提交