17暑假多校联赛1.2 HDU 6034 Balala Power!

Balala Power!

Time Limit: 4000/2000 MS (Java/Others)
Memory Limit: 131072/131072 K (Java/Others)

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

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6034

分析

题意:先给出一个数字n,后面n行是n个由小写字母组成的字符串,规定a到z可以对应0到25任意一个数,但不同的字母不能对应同一个数,但位于字符串第一位的不能对应0,但单独一个字符的字符串可以对应0,将这n个字符串都变为26进制数,每个字符串代表一个数,每个字母代表一位,计算这n个字符串的总和的最大值,并对1e9+7取余,输出格式为”Case #x: y”(第x组测试数据的答案y)

比赛时用一个数组存放各个字母出现位置的总权重,因为数值过大,又在比较之前不能改变,所以一直WA,所以又换了一种方法来做:
因为要输出最大值,所以肯定要将各个字母在n个字符串中出现的位置和数量排序,再按大小一一对应数字,但需要考虑到最小字母是否能与0对应,0应该与哪一个字母对应,可以先定义一个flag数组,来存放该字母是否在首位出现过,如果未出现过就可以为0;而各个字母出现的位置和数量可以存放在二维数组中quan[100010][26]用行来存放在各个字符串中与下标相同的位置出现的次数,列代表26个字母,也可以用结构体存放,用结构体就可以将各个字母存放到结构体中,以便排序之后的使用,在存放二维数组的行时,要考虑到他的进位,每位数满26可以向下一位进一

这里写图片描述这里写图片描述

代码
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 1e5 + 10;
const int MOD = 1e9 + 7;
struct word
{
    int pos;///26个字母
    int time[MAXN];///各个字母在n个字符串中出现的位置和数量,数组下标是位置,对应的值是在该位置出现的次数
}quan[27];
bool cmp(word &a,word &b)///按从小到大的顺序排序结构体
{
    for(int i=MAXN-1; i>1; i--)///从高位往下比较各个字母出现的次数,高位出现的越多,最后乘的值越大
    {
        if(a.time[i]!=b.time[i])
        {
            return a.time[i]<b.time[i];
        }
    }
    return a.time[1]<b.time[1];
}
int main()
{
    int n,N=0;
    char str[MAXN];
    while(scanf("%d",&n)!=EOF)
    {
        int flag[27]={0};///来标记各个字母是否可以对应0
        for(int i=0; i<26; i++)
        {
            quan[i].pos=i;///将26字母按0到25存入结构体
            for(int j=0; j<MAXN; j++)
            {
                quan[i].time[j]=0;///将各个位置出现的次数赋值为0
            }
        }
        while(n--)
        {
            scanf("%s",str);
            int len;
            len=strlen(str);
            if(len>1)flag[str[0]-'a']=1;///如果字符串长度大于1,则第一位字母不能对应0,标记为1
            for(int i=0; i<len; i++)
            {
                int y;
                y=len-i;
                quan[str[i]-'a'].time[y]++;///将i位置的字母对应的数组位置加1
                while(quan[str[i]-'a'].time[y]==26)///当此位置数值大于1就需要往后一位进1
                {
                    quan[str[i]-'a'].time[y]=0;
                    y++;
                    quan[str[i]-'a'].time[y]++;///进1之后还要考虑进1之后是否会让下一位满26,所以用while判断下一位是否需要进1
                }
            }
        }
        sort(quan,quan+26,cmp);///将结构体按各个字母出现的位置及数量从小到大排序
        int op,m=1;
        long long sum=0,sumi=0,me;///不用long long会WA
        for(int i=0; i<26; i++)
        {
            if(flag[quan[i].pos]==0)
            {
                op=i;///op存放出现的位置及数量最小又可以对应0的字母在结构体数组中对应的下标
                break;
            }
        }
        for(int i=0; i<26; i++)
        {
            sumi=0;
            if(i==op)
            {
                me=0;///将i位对应0
            }
            else
            {
                me=m;///将各位一一对应1到25
                m++;
            }
            for(int j=MAXN-1;  j>0; j--)///将26进制转为10进制,第n位置需要乘以26的(n-1)次方,所以倒着计算,每次乘以1个26即可
            {
                sumi=(sumi*26)%MOD;///不断取余
                sumi=(sumi+(long long)quan[i].time[j]*me)%MOD;///将每位都乘以字母对应的数值并取余
            }
            sum=(sum+sumi)%MOD;///将每个字母计算得出的值加入总和
        }
        N++;
        printf("Case #%d: %lld\n",N,sum);///输出格式不能忘,因为这个坑错了好几次
    }
}
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值