只能说这一题有点坑,需要细心,我错在一个自己以为对的地方wa了44发。
题意:给一个n,输入n个由小写之母组成的串,每个字母可以且只能对应0 -->25中的一个值。组成的数是26进制,问你怎样对应值才能得到最大的10进制,且输出值。
题目中提醒了前导不能为0。这是一个比较明显的坑。
我们可以先求出字符x,在m位出现了多少次,若>= 26次,则进位。从最高位开始,对字符出现的次数进行排队。比如1000 是大于999的,位数越高才越大。接下来,需要考虑0的情况。若字符m为前导,那么它不能为0,若它是最小值需要找到最小的不为前导的数n,然后值依次右移(本题中)。这是一个较隐蔽的坑,我就是这里一直wa,以为右移绝对正确,其实是n找错了。
/*
ID: DickensTone
LANG: C++
PROB: palsquare
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int mod = 1e9 + 7;
const int maxn = 100000 + 7;
int num[30][maxn];
bool vis[30];
int val[30];
int id[30];
int maxl = 0;
bool have[28];
bool cmp(int x, int y)
{
for(int i = maxl; i >= 0; i--)
{
if(num[x][i] != num[y][i]) return num[x][i] > num[y][i];
}
return false;
}
void print()
{
for(int i = 0; i <= 25; i++)
printf("%d %d\n", id[i], num[id[i]][0]);
printf("--------------------\n");
for(int i = 0; i <= 25; i++)
printf("%d %d\n", val[id[i]], id[i]);
}
int main()
{
int kase = 1;
int n;
long long k[maxn];
k[0] = 1;
for(int i = 1; i < maxn; i++)
k[i] = (k[i - 1] * 26) % mod;
while(scanf("%d", &n) == 1)
{
maxl = 0;
memset(vis, 0, sizeof(vis));
memset(have, 0, sizeof(have));
memset(num, 0, sizeof(num));
char str[maxn];
for(int i = 0; i <= 26; i++)
id[i] = i;
for(int i = 0; i < n; i++)
{
scanf("%s", str);
int len = strlen(str);
if(len > 1) vis[str[0] - 'a'] = 1;
for(int l = len - 1; l >= 0; l--)
{
//printf("yes\n");
int p = len - 1 - l;
num[str[l] - 'a'][p] += 1;
have[str[l] - 'a'] = 1;
while(num[str[l] - 'a'][p] == 26)
{
num[str[l] - 'a'][p++] = 0;
num[str[l] - 'a'][p] += 1;
}
maxl = max(maxl, p);
}
}
//printf("%d\n", vis[25]);
//printf("%d\n", id[2]);
sort(id, id + 26, cmp);
int init = 25;
for(int i = 0; i <= 25; i++)
{
val[id[i]] = init--;
//printf("%d %d\n", id[i], init + 1);
}
if(vis[id[25]] == 1)
{
//printf("yes\n");
int t = 1;
while(vis[id[25 - t]])
{
t++;
//printf("%d\n", t);
}
for(int i = 25; i > 25 - t; i--)
val[id[i]] = val[id[i - 1]];
val[id[25 - t]] = 0;
}
//print();
//printf("%d\n", id[2]);
long long ans = 0;
for(int i = 0; i <= 25; i++)
{
if(!have[i]) continue;
//printf("%d\n", n);
for(int j = 0; j <= maxl; j++)
{
if(num[i][j])
ans = (ans + (val[i] * k[j] * num[i][j]) % mod) % mod;
}
//printf("%lld\n", ans);
}
printf("Case #%d: %lld\n", kase++, ans);
}
return 0;
}