hdu多校联赛 Balala Power!

Balala Power!

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 4809    Accepted Submission(s): 387


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.  (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

hdu 7月25日多校联赛 1002

  这道题做的时候就没看懂题意 结束后听别人说才懂题意 题意说起来不麻烦 不过不好解释 输入一个数 在输入这个数个数的字符串 由字母a-z 构成 你对a-z这26个字母 赋以0-25这26个数值 然后这些字符串看成26进制的数 求这些字符串赋值后形成的数的的合的最大值是多少 但那是要注意不能出现前导零 即数的第最大位的值不能为0 

至于北航给的题解 感觉十分坑人 各位看官可以感受下: 

每个字符对答案的贡献都可以看作一个 26 进制的数字,问题相当于要给这些贡献加一个 0 到 25 的权重使得答案最大。最大的数匹配 25,次大的数匹配 24,依次类推。排序后这样依次贪心即可,唯一注意的是不能出现前导 0。

感觉和解释了一遍题没啥区别 幸好最后还给了标程 可惜标程也没吃透 只能照着标程强行解释一波

标程:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;


const int N = 100020;
const int Q = 1e9 + 7;
int n , L;
int num[26][N];//num数组用来统计这26个字母在n数位上的个数
int power[N] , sum[N];
bool ban[26];//代表26个字母


char str[N];
int a[26];


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;
}


void work() {
    memset(num , 0 , sizeof(num));
    memset(ban , 0 , sizeof(ban));
    memset(sum , 0 , sizeof(sum));
    L = 0;
    for (int i = 0 ; i < n ; ++ i)
        {
        scanf("%s" , str);//str用来存字符串
        int len = strlen(str);
        if (len > 1)
        {
            ban[str[0] - 'a'] = 1;//字符串首个字母 在ban数组中的数值为1 即统计每个字符串的首字母
        }
        reverse(str , str + len);//字符串里字母的顺序调换
        for (int j = 0 ; j < len ; ++ j) //便历字符串
        {
            ++ num[str[j] - 'a'][j];//当前字母在j这一数位上的数量
            sum[str[j] - 'a'] += power[j];//所有这一数位上的和 (只看这一数位所有串的和)
            if (sum[str[j] - 'a'] >= Q) //判断这一数位上的和大小是否打一 le9+7(和取模一个效果)
            {
                sum[str[j] - 'a'] -= Q;//如果大于则减去 le9+7
            }
        }
        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;//对所有串和的位数个数进行26进制进位处理
            num[i][j] %= 26;
        }
        while (num[i][L])
        {
            num[i][L + 1] += num[i][L] / 26;//对最后一个数位上的数进行26进制进位处理
            num[i][L ++] %= 26;
        }
        a[i] = i;//a数组中的0—25 代表了字母a-z
    }
    sort(a , a + 26 , cmp);//对这26个字母在所有数位上的个数进行升序排序
    int zero = -1;//用zero为标记 赋值初值为-1
    for (int i = 0 ; i < 26 ; ++ i)
    {
        if (!ban[a[i]])
        {
            zero = a[i];//找到最大的不能为前导零的那个字母 并进行标记
            break;
        }
    }
    int res = 0 , x = 25;
    for (int i = 25 ; i >= 0 ; -- i)
    {
        if (a[i] != zero)//标记的字母跳过
        {
            res += (LL)(x --) * sum[a[i]] % Q;//对符合前导零的字母进行求和
            res %= Q;//每一位求和后都取模
        }
    }
    static int ca = 0;
    printf("Case #%d: %d\n" , ++ ca , res);
}


int main() {
    power[0] = 1;
    for (int i = 1 ; i < N ; ++ i)
    {
        power[i] = (LL)power[i - 1] * 26 % Q;//将所有26进制位上的数值进行打表
    }
    while (~scanf("%d" , &n))
    {
        work();
    }
    return 0;
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

     
    
    • 1
      点赞
    • 0
      收藏
      觉得还不错? 一键收藏
    • 0
      评论
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

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

    抵扣说明:

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

    余额充值