HDU 6034 Balala Power!【贪心】

来源:互联网 发布:2017网络神曲 编辑:程序博客网 时间:2024/05/24 02:56

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

题意:

给你字母串,赋值0-25之间的26进制数,加和,使结果最大,但不能有前导0即此字母不能作为某一串的前缀出现。

想法:

先处理不是0的字母。

比较每个字母在各位上出现的次数,肯定是在高位上出现的次数越大,给字母赋越大的值。所以当低位满26时,要向高位进1位。同时存下转换成26进制的幂数和,这样最后赋值的时候直接数字x幂数和即为结果。

接下来处理前导0的问题。(只有26个字母全都出现的时候,才会有一个字母一定为0)

当该字母串的长度>1时,首字母肯定不能为0。起初先判断这个字母是否出现在第一位,否则从小到大扫过去,找到最小的能被赋值为0的。

╮(╯▽╰)╭感觉讲的还是乱乱的 看代码吧

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;typedef long long ll;const int mod=1e9+7;const int maxn=110000;int sum[maxn];//各位上某字母幂数的总和int p[maxn];//某位上的26进制形式int vis[maxn];//某个字母是否出现在第一位int num[26][maxn];//某位上的某字母出现的次数int a[26];//int l,n;bool  cmp(int a,int b){    for(int i=l-1; i>=0; --i )    {        if(num[a][i]!=num[b][i])            return num[a][i]<num[b][i];    }    return 0;}int solve(){    memset(num, 0, sizeof(num));    memset(vis, 0, sizeof(vis));    memset(sum, 0, sizeof(sum));    l=0;    char s[maxn];    for(int i=0;i<n;++i)    {        scanf("%s",s);        int len=strlen(s);        if(len>1)        {            vis[s[0]-'a']=1;//表示不能变成0        }        reverse(s, s + len);//将字符串翻转过来        for(int j=0; j<len; ++j)        {            num[s[j]-'a'][j]++;            sum[s[j]-'a']+=p[j];            if(sum[s[j]-'a']>=mod)                sum[s[j]-'a']%=mod;        }        l=max(l,len);    }    for(int i=0; i<26; ++i)    {        for(int j=0; j<l; ++j)//表示除最高位的低位向最高位进位        {            num[i][j+1]+=num[i][j]/26;            num[i][j]%=26;        }        while(num[i][l])        {            num[i][l+1]+=num[i][l]/26;//表示最高位再进位            num[i][l++]%=26;        }        a[i]=i;    }    sort(a,a+26,cmp);    int zero=-1;    for(int i=0;i<26;++i)    {        if(!vis[a[i]])//如果不是26个字母全出现的话 这样循环跑一圈zero=25        {            zero=a[i];            break;        }    }    int last=0,x=25;    for(int i=25; i>=0; --i)    {        if(a[i]!=zero)//当遇到那个赋值为0的数,跳过给别的字母赋值        {//也就是说这里省略了计算0            last+=(ll)(x--)*sum[a[i]]%mod;            last%=mod;        }    }    return last;}int main(){    p[0]=1;    for(int i=0; i<maxn; ++i)//计算26进制的幂数        p[i+1]=(ll)p[i]*26%mod;    int cnt=1;    while(~scanf("%d",&n))    {        printf("Case #%d: %d\n",cnt++,solve());    }    return 0;}

ps:比赛时一群人理解这个题简直要吐血 (暴风旋转哭泣.jpg)
我真的再也不想看到巴啦啦了QAQ

原创粉丝点击