HDU6304(Balala Power!)

本文介绍了一道HDU在线评测平台上的字符串处理题的解题思路与实现代码。该题通过将字符串转换为26进制数表示,并对这些数值进行相加操作来解决问题。文章详细解释了如何使用多项式表示字符串,如何提取公因式进行排序,以及如何处理前导零等问题。
摘要由CSDN通过智能技术生成

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6034

把所有的字符串用 26 的多项式表示,所有字符串的和就是多项式相加,按照字母提取公因式,整理成26进制,作为字母的系数,按照系数给字母排序,系数越大的字母分配的权值越大。

关于前导零的处理,可以在排完序之后,从不是首字母的字母中选出排名最靠后的那一个,记录为0,最后分配权值和累加答案的时候跳过。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string.h>
#include <stdlib.h>
#include <set>
#include <algorithm>
using namespace std;

typedef long long unsigned int ull;
typedef long long ll;

const int maxL = 100000 + 10;
const ull mod = 1e9 + 7;

int f[27][maxL];
ull expp[maxL];
char S[maxL];
bool first[26];
int a[26];
ull w[26];
int n;

void init(){
    expp[0] = 1;
    for (int i=1; i<maxL; i++){
        expp[i] = expp[i-1] * 26;
        expp[i] %= mod;
    }
}

int cmp(int a, int b){
    if (f[a][0] != f[b][0])
        return f[a][0] > f[b][0];

    for (int i=f[a][0]; i>=1; i--){
        if (f[a][i] != f[b][i])
            return f[a][i] > f[b][i];
    }
    return 0;
}

int main()
{
    init();

    int t = 0;
    while (~scanf("%d", &n)){
        t++;

        memset(f, 0, sizeof(f));
        memset(first, false, sizeof(first));
        memset(w, 0, sizeof(w));
        for (int i=0; i<n; i++){
            scanf("%s", S);
            first[S[0] - 'a'] = true;
            int len = strlen(S);
            reverse(S, S+len);

            for (int j=0; j<len; j++){
                int k = S[j] - 'a';
                f[k][j+1]++;
                if (j+1 > f[k][0]) f[k][0] = j+1;
                w[k] = (w[k] + expp[j]) % mod;
            }
        }

        for (int i=0; i<26; i++){
            for (int j=1; j<=f[i][0]; j++){
                f[i][j+1] += f[i][j] / 26;
                f[i][j] %= 26;
            }

            int len = f[i][0];
            while (f[i][len] > 0){
                f[i][len+1] += f[i][len] / 26;
                f[i][len] %= 26;
                len++;
            }
            f[i][0] = len;
        }

        for (int i=0; i<26; i++) a[i] = i;
        sort(a, a+26, cmp);

        int zero = 0;//记录权值为 0 的字母
        for (int i=25; i>=0; i--){
            if (!first[a[i]]){
                zero = a[i];
                break;
            }
        }

        ull ans = 0;
        int x = 25;
        for (int i=0; i<26; i++){
            if (zero == a[i]) continue;
            ans += (w[a[i]] * (ull)(x--)) % mod; //这里不要用(26-i-1),因为可能会跳过权值为0的字母
            ans %= mod;
        }
        cout << "Case #" << t << ": " << ans << endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值