2017 Multi-University Training Contest

来源:互联网 发布:如何带端口ping 编辑:程序博客网 时间:2024/05/17 18:02


Balala Power!

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


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 base26 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
1a2aabb3abaabc
 

Sample Output
Case #1: 25Case #2: 1323Case #3: 18221
 

Source
2017 Multi-University Training Contest - Team 1
 
2017年多校联赛第一场,第一场感觉虐的很惨,算是去做了签到题目,做这个题目的时候,思想都想到了,最后就是处理
优先级的时候导致超时。

最开始就用二维数组来统计某个字母再某个位出现的次数,当时时想所在位越高,而且再高位出现次数越多就安排较大值。
这种思想时正确的。可是中间忘考虑到进位的问题。后来写完后侧了一组数据27 ab,26个b字符串发现答案不正确。
才发现低位置上的字符个数满26可以顶一个高位的字符,就像10进制,10个10就顶一个100.解决进位后,我们搞优先级。
从高位把最大次数一样多的找出来,层层向地位进行筛选,直到剩余一个数,或者到最低位了剩余多个数,都可以确定
字母的号码,最后考虑前导0,只有26个字母都出现的时候才会有个字母是0,对这种情况再单独考虑,如果一个字母它是
0,但它不能是0,就与是对应1的那个字母进行交换,交换完后看这个字母能不能是0,不能是0就与2对应的字母交换,直到
交换到一个符合的。最终超时了,超时部分主要就在优先级处理那一块,循环次数太多了。
看了标准后,发现直接就是使用排序,不过使用构造函数,对于两个字母的优先级,则从最高位到最低位依次比较其相同位上出
现的次数,如果某个位置上,第一个字符出现的次数小于第二个字符出现的次数,则第二个字符优先级就高。
而且标准那样进行排序,还是我第一见排序的构造函数还能那样写,好牛逼,真的是扩展思路了。

AC代码:

#include <iostream>#include <stdio.h>#include <string>#include <string.h>#include <algorithm>using namespace std;typedef long long LL;const int maxn = 100010;const int mod = 1e9+7;  ///模值LL num[30][maxn];      ///num[i][j]代表i+'a'这个字母在第j位出现的次数int isok[30];           ///用来存放i+'a'这个字母是否可以是0,可以设置为0,不可以设置为1int power[30];          ///存放对应的权值int a[30];int maxbit;             ///每租数据的最高位。string str[maxn];       ///存放字符串///计算字符串的值LL calculate(string s){    LL ans = 0;    for(int i = 0; i < s.length(); i++)        ans = (ans*26+power[s[i]-'a'])%mod;    return ans;}bool cmp(int num1,int num2){    for(int i = maxbit; i >= 0; i--)    {        if(num[num1][i] != num[num2][i])            return num[num1][i] < num[num2][i];    }    return 0;}int main(){    int Case = 0,n;    while(~scanf("%d",&n))    {        maxbit = -1;        memset(num,0,sizeof(num));        memset(isok,0,sizeof(isok));        for(int i = 0; i < n; i++)        {            cin>>str[i];            int len = str[i].length();            if(len > 1)            {                isok[str[i][0]-'a'] = 1;  ///受字母不能作为前导            }            for(int j = len-1; j >= 0; j--)            {                int k = str[i][j]-'a';                num[k][len-1-j]++;            }            maxbit = max(maxbit,len-1);        }        for(int i = 0; i < 26; i++)        {            for(int j = 0; j < maxbit; j++)            {                num[i][j+1] += num[i][j]/26;                num[i][j] = num[i][j]%26;            }            a[i] = i;        }        sort(a,a+26,cmp);  ///优先级从小到大排序。        int not_ok=-1;        for(int i = 0; i < 26; i++)        {            if(!isok[a[i]])            {                not_ok = a[i];                break;            }        }        int num = 25;        for(int i = 25; i>=0 ;i--)        {            if(not_ok==a[i])            {                power[a[i]] = 0;            }            else            {                power[a[i]] = num;                num--;            }        }        LL ans = 0;        for(int i = 0; i < n; i++)        {            ans = (ans + calculate(str[i]))%mod;        }        printf("Case #%d: %lld\n",++Case,ans);    }    return 0;}

原创粉丝点击