HDU 6034 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 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

題意:

給你字母串,賦值0-25之間的26進制數,加和,使結果最大,但不能有前導0即此字母不能作爲某一串的前綴出現。

想法:

先處理不是0的字母。

比較每個字母在各位上出現的次數,肯定是在高位上出現的次數越大,給字母賦越大的值。所以當低位滿26時,要向高位進1位。同時存下轉換成26進制的冪數和,這樣最後賦值的時候直接數字x冪數和即爲結果。

接下來處理前導0的問題。(只有26個字母全都出現的時候,纔會有一個字母一定爲0)

當該字母串的長度>1時,首字母肯定不能爲0。起初先判斷這個字母是否出現在第一位,否則從小到大掃過去,找到最小的能被賦值爲0的。

╮(╯▽╰)╭感覺講的還是亂亂的 看代碼吧

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int maxn=110000;
int sum[maxn];//各位上某字母冪數的總和
int p[maxn];//某位上的26進制形式
int vis[maxn];//某個字母是否出現在第一位
int num[26][maxn];//某位上的某字母出現的次數
int a[26];//
int l,n;
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;
}
int solve()
{
    memset(num, 0, sizeof(num));
    memset(vis, 0, sizeof(vis));
    memset(sum, 0, sizeof(sum));
    l=0;
    char s[maxn];
    for(int i=0;i<n;++i)
    {
        scanf("%s",s);
        int len=strlen(s);
        if(len>1)
        {
            vis[s[0]-'a']=1;//表示不能變成0
        }
        reverse(s, s + len);//將字符串翻轉過來
        for(int j=0; j<len; ++j)
        {
            num[s[j]-'a'][j]++;
            sum[s[j]-'a']+=p[j];
            if(sum[s[j]-'a']>=mod)
                sum[s[j]-'a']%=mod;
        }
        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;
            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);
    int zero=-1;
    for(int i=0;i<26;++i)
    {
        if(!vis[a[i]])//如果不是26個字母全出現的話 這樣循環跑一圈zero=25
        {
            zero=a[i];
            break;
        }
    }
    int last=0,x=25;
    for(int i=25; i>=0; --i)
    {
        if(a[i]!=zero)//當遇到那個賦值爲0的數,跳過給別的字母賦值
        {//也就是說這裏省略了計算0
            last+=(ll)(x--)*sum[a[i]]%mod;
            last%=mod;
        }
    }
    return last;
}
int main()
{
    p[0]=1;
    for(int i=0; i<maxn; ++i)//計算26進制的冪數
        p[i+1]=(ll)p[i]*26%mod;
    int cnt=1;
    while(~scanf("%d",&n))
    {
        printf("Case #%d: %d\n",cnt++,solve());
    }
    return 0;
}

ps:比賽時一羣人理解這個題簡直要吐血 (暴風旋轉哭泣.jpg)
我真的再也不想看到巴啦啦了QAQ

發佈了87 篇原創文章 · 獲贊 8 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章