题目链接

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

题意:

小写字母'a''z'对应于数字025,但是那个字母对应某一个数字这个是不知道的,但是要求一个字母只能唯一的对应一个数字,给定一些字符串,然后将字符串对应的数字表示出来后将这个数字看作26进制来进行转换位10进制,找出一种对应关系使得这些字符串转换后的数字的和最大。还需要注意的一点就是说每一个字符串如果长度大于1的话,那么他的第一个字母表示的数字不能够是0。

分析:

如果不考虑字符串的前导不能为0的话,还是比较好解决的,定义:

num[i][j]:表示字母(i+'a')在第j个位置出现的次数。

bj[i]:表示字母(i+'a')有没有作为首字母出现过。

sum[i]:表示的是字母(i+'a')的所有后面需要呈上的幂次和,因为不管这个字母表示的数字是几,但是因为这个数字没每一个字符串中的位置都不会变化,也就是说它后面需要乘上的那个幂次不会发生变化。

a[26],含义就是说a[i]=j表示i这个数字对应的是字母(j+'a')

了解了这些定义之后呢,集体的看一下解题思路,

因为进行进制转换的时候都是从后往前计算,所以必须将整个的字符串给逆序,这里运用了一个字符串逆序函数(reverse()),逆序中i后我们就可以很好的统计每个字母在任意一个位置出现的次数。

次数统计好之后,我们就要考虑如何给每一个字母对应值了,能想到的肯定是如果某一个字母它的最高位置越大,那么这个字母所表示的数字应该越大,那么如果说两个字母的最高位置是一样的呢?那么我就就要接着往下比较他们的次高位置,还是一样的道理,一直往下比较下去直到它们在同一个位置出现的次数不一样为止。这些字母是在数组a中进行排序的,拍好后就是这些字母对应的小到大的顺序。

然后我们考虑前导字母表示的数字不能够为数字0,(出现在这种情况也就意味着26个字母都出现了)。这样我们肯定能够在非前导中找到一个对应的数字最小的,然后将它对哦赢得数组看作0,然后其余的对应的数字小于该数字的所有字母对应的数字依次向前对应一位。

代码:(附详细注释)

#include<stdio.h>
#include<iostream>
#include<string.h>
#include <algorithm>
const int L=100020;
const int mod=1e9 + 7;
typedef long long ll;
using namespace std; int num[26][L];///num[i][j]表示第i个字母在位置j出现的次数
int bj[26];///标记字母有没有在首位出现
int Mi[L],sum[L];///分别表示26的幂和某一个字母总共的次方和
int max_len=-1;
int n,Case=0;;
char str[L];///保存输入的字符串
int a[26];///含义就是说a[i]=j表示i这个数字对应的是字母(j+'a')
void inif()///所有的数组完成一个初始化的功能
{
memset(num,0,sizeof(num));
memset(bj,0,sizeof(bj));
memset(sum,0,sizeof(sum));
} ///这个排序也就是相当于将每一个字母所对应的数字按照从小到大的顺序排好
bool cmp(int n1,int n2)/// 用n1,n2分别表示的是两个字母(该字母可以表示为n1+'a',n2+'a'),并不是他们所对应的数字
{
for(int i=max_len-1; i>=0; i--)
{
if(num[n1][i]!=num[n2][i])
return num[n1][i]<num[n2][i];///然后按照这两个字母在同一个位置出现次数按照从小到大排序
}
return 0;
}
void solve()
{
inif();
for(int i=0; i<n; i++)
{
scanf(" %s",str);
int len=strlen(str);
if(len>1)
bj[str[0]-'a']=1;
reverse(str , str + len);///字符串倒置,就是将整个字符串的位置颠倒过来
for(int j=0; j<len; j++)
{
num[str[j]-'a'][j]++;///该字母在当前位出现的次数加加
sum[str[j]-'a']+=Mi[j];
/*
最开始的时候不理解这里是什么意思,就是说不管一个字母表示的数字如何变化,但是它所在的位数是不会
变化的,也就是说它后面需要乘上的26的几次方不会发生变化
*/
if(sum[str[j]-'a']>=mod)
sum[str[j]-'a']%=mod;
}
max_len=max(len,max_len);
}
for(int i=0; i<26; i++)
{
for(int j=0; j<max_len; j++)
{
num[i][j+1]+=num[i][j]/26;
num[i][j]%=26;
}
while(num[i][max_len])///是说最高位上的某个字母的个数已经超过26了,为了计算方便则向前进一位
{
num[i][max_len+1]=num[i][max_len]/26;///看能不能向前进一位
num[i][max_len]%=26;///保留当前位上的个数
max_len++;///字符串总长度及加
}
a[i]=i;///表示的是当前字母所对应的数字,暂时先这样定义,也相当于一个初始化过程
} sort(a,a+26,cmp);///关键在于看懂这个函数的排序规则,排完之后就是每一个字母所对应的数字了 int ans=-1;
for(int i=0; i<26; i++)
{
if(!bj[a[i]])
{
ans=a[i];
break;
}
} int res=0,x=25;
for(int i=25; i>=0; i--)
{
if(a[i]!=ans)
{
// printf("%d %d\n",a[i],sum[a[i]]);
res+=(ll)(x--)*sum[a[i]]%mod;///只有这个字母出现过,sum[a[i]]才有值
res%=mod;
}
} printf("Case #%d: %d\n",++Case,res); }
int main()
{
Mi[0]=1;
for(int i=1; i<L; i++)
{
Mi[i]=(ll)Mi[i-1]*26%mod;
//printf("%d\n",Mi[i]);
}
while(~scanf("%d",&n))
{
solve();
}
}

2017ACM暑期多校联合训练 - Team 1 1002 HDU 6034 Balala Power! (字符串处理)的更多相关文章

  1. 2017ACM暑期多校联合训练 - Team 8 1002 HDU 6134 Battlestation Operational (数论 莫比乌斯反演)

    题目链接 Problem Description The Death Star, known officially as the DS-1 Orbital Battle Station, also k ...

  2. 2017ACM暑期多校联合训练 - Team 7 1002 HDU 6121 Build a tree (深搜+思维)

    题目链接 Problem Description HazelFan wants to build a rooted tree. The tree has n nodes labeled 0 to n− ...

  3. 2017ACM暑期多校联合训练 - Team 6 1001 HDU 6096 String (字符串处理 字典树)

    题目链接 Problem Description Bob has a dictionary with N words in it. Now there is a list of words in wh ...

  4. 2017ACM暑期多校联合训练 - Team 6 1002 HDU 6097 Mindis (数学)

    题目链接 Problem Description The center coordinate of the circle C is O, the coordinate of O is (0,0) , ...

  5. 2017ACM暑期多校联合训练 - Team 4 1004 HDU 6070 Dirt Ratio (线段树)

    题目链接 Problem Description In ACM/ICPC contest, the ''Dirt Ratio'' of a team is calculated in the foll ...

  6. 2017ACM暑期多校联合训练 - Team 9 1005 HDU 6165 FFF at Valentine (dfs)

    题目链接 Problem Description At Valentine's eve, Shylock and Lucar were enjoying their time as any other ...

  7. 2017ACM暑期多校联合训练 - Team 9 1010 HDU 6170 Two strings (dp)

    题目链接 Problem Description Giving two strings and you should judge if they are matched. The first stri ...

  8. 2017ACM暑期多校联合训练 - Team 8 1006 HDU 6138 Fleet of the Eternal Throne (字符串处理 AC自动机)

    题目链接 Problem Description The Eternal Fleet was built many centuries ago before the time of Valkorion ...

  9. 2017ACM暑期多校联合训练 - Team 8 1011 HDU 6143 Killer Names (容斥+排列组合,dp+整数快速幂)

    题目链接 Problem Description Galen Marek, codenamed Starkiller, was a male Human apprentice of the Sith ...

随机推荐

  1. LintCode-112.删除排序链表中的重复元素

    删除排序链表中的重复元素 给定一个排序链表,删除所有重复的元素每个元素只留下一个. 样例 给出 1->1->2->null,返回 1->2->null 给出 1-> ...

  2. TCP系列35—窗口管理&流控—9、紧急机制

    一.概述 我们在最开始介绍TCP头结构的时候,里面有个URG的标志位,还有一个Urgent Pointer的16bits字段.当URG标志位有效的时候,Urgent Poinert用来指示紧急数据的相 ...

  3. idea快捷键操作

    在编写代码的时候直接输入psv就会看到一个psvm的提示,此时点击tab键一个main方法就写好了. psvm 也就是public static void main的首字母. 依次还有在方法体内键入f ...

  4. PHP获取网页内容的几种方法

    方法1: 用file_get_contents以get方式获取内容 <?php $url='http://www.domain.com/?para=123'; $html= file_get_c ...

  5. SFTPHelper

    public class SFTPHelper { #region 字段或属性 private readonly SftpClient _sftp; /// <summary> /// S ...

  6. java List接口实现类

    首先看这两类都实现List接口,而List接口一共有三个实现类,分别是ArrayList.Vector和LinkedList.List用于存放多个元素,能够维护元素的次序,并且允许元素的重复.3个具体 ...

  7. cmake & make

    大家都知道,写程序大体步骤为: 1.用编辑器编写源代码,如.c文件. 2.用编译器编译代码生成目标文件,如.o. 3.用链接器连接目标代码生成可执行文件,如.exe. 但如果源文件太多,一个一个编译时 ...

  8. java 中 Stringbuff append源代码浅析

    public synchronized StringBuffer append(String str) {        super.append(str);        return this;  ...

  9. 前端开发学习之——使用jquery/javascript判断及改变checkbox选中状态

    一.使用jquery判断及改变checkbox选中状态 1.使用JQuery判断一个checkbox 是否为选中: (1).attr('checked) 看JQuery版本1.6+返回:”checke ...

  10. 【以前的空间】poj 2288 Islands and Bridges

    一个不错的题解 : http://blog.csdn.net/accry/article/details/6607703 这是一道状态压缩.每个点有一个值,我们最后要求一个最值sum.sum由三部分组 ...