2017 Multi-University Training Contest

来源:互联网 发布:网络总监招聘 编辑:程序博客网 时间:2024/06/08 16:45

题目链接

题意
给定多个字符串,给二十六个字母赋予0~25的值,每个字符串形成一个26进制的数字,求怎么分配权值使得这几个字符串的和最大。

思路
官方:每个字符对答案的贡献都可以看作一个 26 进制的数字,问题相当于要给这些贡献加一个 0 到 25 的权重使得答案最大。最大的数匹配 25,次大的数匹配 24,依次类推。排序后这样依次贪心即可,唯一注意的是不能出现前导 0。
建一个26进制的数组num[26][100010]分别表示每一位的每一个字母有多少个,当超过26时向前进一位,然后进行排序,进行赋值。排序是先开一个26的数组表示每个字母所代表数字的顺序
代码(参考标程)

#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<string>#include<vector>#include<stack>#include<bitset>#include<cstdlib>#include<cmath>#include<set>#include<list>#include<deque>#include<map>#include<queue>#include<cstdio>using namespace std;typedef long long ll;const int INF = 0x3f3f3f3f;const int MOD = 1e9+7;const int MAXN = 100015;int n, L;int Case = 1;int num[26][MAXN];int power[MAXN], s[MAXN];bool b[26];char str[MAXN];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];         }    }}void solve (){    memset (num, 0, sizeof (num));    memset (b, 0, sizeof (b));    memset (s, 0, sizeof (s));    L = 0;    for (int i=0; i<n; ++i)    {        scanf ("%s", str);        int len = strlen (str);        if (len > 1)            b[str[0] - 'a'] = 1;        reverse (str, str + len);        for (int j=0; j<len; ++j)        {            num[str[j] - 'a'][j] ++;            s [str[j] - 'a'] += power[j];            if (s[str[j] - 'a'] >= MOD)                s [str[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 (!b[a[i]])        {            zero = a[i];            break;        }    }    int res = 0, x = 25;    for (int i=25; i>=0; --i)    {        if (a[i] != zero)        {            res += (ll) (x--) * s [a[i]] % MOD;            res %= MOD;        }    }     printf("Case #%d: %d\n" ,Case++ , res);}int main (){    power [0] = 1;    for (int i=1; i<MAXN; ++i)        power [i] = (ll) power[i-1] * 26 % MOD;    while (~scanf ("%d", &n))    {        solve();    }    return 0;}
原创粉丝点击