hdu6034--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 froma toz into each number ranged from 0 to25, 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. (1n100000)

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
 

题意

巴拉拉能量???不存在的。。再见
唐先生有n个字符串,都由小写字母 a-z 组成。
现将每个字母用0-25的其中一个数表示,且不同字母表示的数不同。
如果将每个字符串看成一个26进制的数,中间的每个字母都是一个26进制数
且每个字符串不能以0开头(除非这个字符串是“0”)
求怎样组合a-z的权值,可以使得所有26进制数的和最大。
将这个和以10进制数输出(mod 1e9+7)

分析

这个题细节非常多,当然,做法也并不唯一。
要统计这26个字母在各位上出现的次数,当然,满26要进位。
然后排序,按照权值求和

具体实现如下
1. 设置26个结构体组c[26],里面存放一个num[maxn]的char数组,和该字母的权值flag。
2. num[i]初始化为0,flag初始化为0-25
3. 输入n个字符串,统计各字符出现次数,即:字符串长为len
如果字符串第i位的字母是x,那么c[x-'a']的num[len-i]++(循环从0开始,所以是num[len-1-1]++)
将出现的字符的visit设置为1
4. 将结构体c[26] 按照最高位大小排序,设置一个cmp
5. 设置一个init()函数,用于记录26进制每一位的权值,比如第i位,就是26^(i-1)
6. 计算各字母权值*位数的和,计算各字符串的和
7. 但是要注意,题目虽然说一定有一个字母没有出现在最高位过,保证了一定存在合法的映射,(合法即不能出现前导零),但是排序后的序列可能将出现在最高位过的字母排到最后一位,赋值为0就非法了。所以这种情况需要特判,然后从后往前找第一个没出现在最高位的字母替换到最后,前面依次迁移。(网上dalao说的哈哈哈哈)
 


代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define maxn 100007
#define mod 1000000007
typedef  long long  LL;
using namespace std;
int visit[27];
long long m[maxn];
long long re[maxn];
void init()
{
    m[0]=1;
    LL now=1;
    for(int i=1; i<=100000; i++)
    {
        now*=26;
        m[i]=now%mod;
        now=now%mod;
    }
}
struct node
{
    int flag;
    char num[maxn];
} c[27];
bool cmp(node a,node b)
{
    for(int i=maxn-1; i>0; i--)
    {
        if(a.num[i]!=b.num[i])
            return a.num[i]>b.num[i];
    }
    return a.num[0]>b.num[0];
}
int main()
{
    int n;
    init();
    int pp=0;
    while(~scanf("%d",&n))
    {
        char str[maxn];
        //memset(visit,0,sizeof(visit));
        for(int i=0; i<26; i++)
        {
            c[i].flag=i;
            visit[i]=0;
            for(int j=0; j<maxn; j++)
              c[i].num[j]=0;
        }

        for(int i=1; i<=n; i++)
        {
            scanf("%s",str);
            int l=strlen(str);
            if(l!=1)visit[str[0]-'a']=1;
            for(int j=0; j<l; j++)
            {
                int t=str[j]-'a';
                int y=l-j-1;
                c[t].num[y]++;
                while(c[t].num[y]==26)
                {
                    c[t].num[y++]=0;
                    c[t].num[y]++;
                }
            }
        }

        sort(c,c+26,cmp);
        LL ans = 0;
        int f=-1;
        for(int i=25; i>=0; i--)
        {
            if(!visit[c[i].flag])
            {
                f=i;
                break;
            }
        }
        for(int i=0; i<=25; i++)
        {
            if(i==f);
            else if(i<f)
            {
                LL haha=25-i;
                for(int j=maxn; j>=0; j--)
                {
                    (ans+=(LL)haha*m[j]*c[i].num[j])%=mod;
                }
            }
            else
            {
                LL haha=25-i+1;
                for(int j=maxn; j>=0; j--)
                {
                    (ans+=(LL)haha*m[j]*c[i].num[j])%=mod;
                }
            }

        }

        printf("Case #%d: %lld\n",++pp,ans);


    }
    return 0;
}

链接

http://acm.hdu.edu.cn/showproblem.php?pid=6034

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值