1. 程式人生 > >1002 Balala Power!

1002 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 to z 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 10
9
+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到25個數字賦給a到z,然後考慮前導零的情況,若當前字母不能作為前導零,則依次往後類推,把可以作為前導零的往前換。
#include <bits/stdc++.h>
using namespace std;
const int N=100020;
const int mod=1e9+7;
int n;
int L;///記錄字串組中的最大長度
int num[26][N];
int power[26];///power[i]代表26的i次冪
int sum[N];
bool ban[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);
        int len=strlen(str);
        if(len>1)
        {
            ban[str[0]-'a']=1;///記錄第一個字母是否出現過
        }
        reverse(str,str+len);///字串反轉
        for(int j=0;j<len;j++)
        {
            num[str[j]-'a'][j]++;///在第j位上每個字母出現的次數,想一下表
            sum[str[j]-'a']+=power[j];///每個字母出現在j位上,加上26的j次冪
            if(sum[str[j]-'a']>=mod)
            {
                sum[str[j]-'a']-=mod;
            }
        }
        L=max(L,len);
    }

    for(int i=0;i<26;i++)///將每個字母的數量轉化成26進位制數
    {
        for(int j=0;j<L;j++)
        {
            num[i][j+1]+=num[i][j]/26;///滿26進一,將每個字母都轉換成26進位制數
            num[i][j]%=26;
        }
        while(num[i][L])
        {
            num[i][L+1]+=num[i][L]/26;
            num[i][L++]%=26;
        }
        a[i]=i;///每個字母的值初始化
    }

    sort(a,a+26,cmp);
    for(int i=0;i<26;i++)
        cout<<a[i]<<" ";
    cout<<endl;
    int zero=-1;
    for(int i=0;i<26;i++)///找到可以為零的字母
    {
        if(!ban[a[i]])
        {
            zero=a[i];
            cout<<zero<<endl;
            break;
        }
    }
    int res=0,x=25;
    for(int i=25;i>=0;i--)///從後往前對字母依次進行賦值
    {
        if(a[i]!=zero)
        {
            res+=(long long)(x--)*sum[a[i]]%mod;
            res%=mod;
        }
    }
    static int t=0;
    printf("Case #%d: %d\n",++t,res);
}
int main()
{
    power[0]=1;///power[i]代表26的i次冪
    for(int i=1;i<N;i++)
    {
        power[i]=(long long)power[i-1]*26%mod;
    }
    while(scanf("%d",&n)!=EOF)
    {
        work();
    }
    return 0;
}