Balala Power!
Problem Description
Talented Mr.Tang has n strings consisting of only lower case characters. He wants to charge them with Balala Power (he could change each character ranged from a to z into each number ranged from 0 to 25, but each two different characters should not be changed into the same number) so that he could calculate the sum of these strings as integers in base 26 hilariously.
Mr.Tang wants you to maximize the summation. Notice that no string in this problem could have leading zeros except for string "0". It is guaranteed that at least one character does not appear at the beginning of any string.
The summation may be quite large, so you should output it in modulo 109+7.
Input
The input contains multiple test cases.
For each test case, the first line contains one positive integers n, the number of strings. (1≤n≤100000)
Each of the next n lines contains a string si consisting of only lower case letters. (1≤|si|≤100000,∑|si|≤106)
Output
For each test case, output "Case #x: y" in one line (without quotes), where x indicates the case number starting from 1 and y denotes the answer of corresponding case.
Sample Input
1
a
2
aa
bb
3
a
ba
abc
Sample Output
Case #1: 25
Case #2: 1323
Case #3: 18221
题意:
a~z可以任意变为0~25中的任意数,不同字母映射的值不能相同,给你n串字符串,
问把这些字符串中的字母转换成(26进制)数字后,能够得到的最大的和是多少
(字符串转换后的数字不能有前缀0,除了”0”)
思路:
很明显,肯定要先对a~z这26个字母排序,然后依次从25开始赋值了。
根据什么来排序呢,(直接求和得到的)权值?不行,爆longlong
但是我们可以转换一下,依然是求和,我们可以用数组来表示权值的每一位
p[x].num[i]表示字母(x+‘’a’)的第i位为多少
接着则可比较num[i]来对字母进行排序,排好序后赋值,计算即可(具体详见代码)
代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long LL;
const int mod=1e9+7;
const int N=1e5+10;
struct node
{
int val;
int num[N];//num[i]表示第i位上存在多少个val
} q[27];
char str[N];
bool inq[30],vis[30];//vis记录出现的字母,inq记录哪些字母不能为0
int mp[30];
LL table[N];
int n,ps;//ps为字符串最长的长度
bool cmp(node a,node b)
{
for(int i=ps+9; ~i; --i)
if(a.num[i]!=b.num[i])
return a.num[i]>b.num[i];
return 0;
}
void Table()//26的次方打表
{
table[0]=1;
for(int i=1; i<N; ++i)
table[i]=(table[i-1]*26)%mod;
}
void init()//初始化
{
memset(mp,0,sizeof(mp));
memset(inq,false,sizeof(inq));
memset(vis,false,sizeof(vis));
for(int i=0; i<26; ++i)
{
q[i].val=i;
memset(q[i].num,0,sizeof(q[i].num));
}
ps=0;
}
int main()
{
Table();
int t=0;
while(~scanf("%d",&n))
{
init();
for(int i=0; i<n; ++i)
{
scanf("%s",str);
int len=strlen(str);
if(len>1)//不能为0
inq[(str[0]-'a')]=1;
for(int j=0; j<len; ++j)
{
int x=str[j]-'a',y=len-j-1;
vis[x]=1;
q[x].num[y]+=1;
}
ps=max(ps,len);
}
for(int i=0; i<ps+10; ++i)//满26进1,处理进位
for(int j=0; j<26; ++j)
{
q[j].num[i+1]+=q[j].num[i]/26;
q[j].num[i]%=26;
}
sort(q,q+26,cmp);
int flag=-1;//记录为0的那个字母
if(vis[q[25].val])//如果26个字母全存在,说明必要有字母为0
{
for(int i=25; ~i; --i)
{
int x=q[i].val;
if(!inq[x])//将(x+'a')置为0
{
mp[x]=0;
flag=x;
break;
}
}
}
int tot=25;
for(int i=0; i<26; ++i)//依次给字母赋权值
{
int x=q[i].val;
if(vis[x])
{
if(x!=flag)
mp[x]=tot--;
}
else
break;
}
LL ans=0;
for(int i=0; i<ps+10; ++i)
for(int j=0; j<26; ++j)
{
int x=q[j].val;
if(vis[x])
ans=(ans+(mp[x]*table[i]%mod)*q[j].num[i])%mod;
}
printf("Case #%d: %lld\n",++t,ans);
}
return 0;
}
ps:这道题考察的纯粹是sort。。
比赛时也用了这种方法,但是一运行程序输入数据就直接崩溃,最后gg了