POJ6034---Balala Power!(2017多校联赛B题)

来源:互联网 发布:大数据教程视频 编辑:程序博客网 时间:2024/06/09 14:26

【题目来源】:http://acm.hdu.edu.cn/showproblem.php?pid=6034
【题意】
26个英文字母,要求用0~25的数字给每一个英文字母赋值,把每一个字符串变成一个个数字,然后,求和。有以下几点,这些构成的数字是26进制,还有,为了求最大的和,必须合理分配每一个数字代表哪个字母,并且,这些数字不会有前导0,也就是说,0这个数字不能够赋值给任意字符串的第一个字母。
【思路】
解释一下样例1:只有一个字符串,一个字母,赋值为25,最大和值是25。
样例2:两个字符串,a在第二位(相当于十位)上有一个,在第一位(相当于个位)上有一个,记成:1 1
b同理,位1 1,那么这两个的谁赋最大值25都一样,得:1*25+1*25*26,1*24+1*24*26,之和便是答案。(至于为啥乘26,想一下十进制,,,每次都乘以10)
样例3:
字母a在第一位上有2个,在第三位上有一个,记为:2 0 1
字母b在第二位上有两个,记为:0 2 0
字母c在第一位上有一个,记为:1 0 0
那么现在进行比较,给哪个赋哪个比较合适,因为各自的最终结果格式都是:第一位数字赋值+第二位数字赋值26+第三位数字赋值*26*26。
思考过后,会发现给a赋值25,b赋值为24,c赋值为23较为合理。
我的大致思路基本上已经在样例里说清楚了,总的来说,就是用数组记下每种字母的位置的个数,然后利用自定义cmp函数进行比较,贪心。
【代码】

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int mod=1e9+7;typedef long long LL;char s[100000+10];int len;struct pp{    bool index;//判断是否在第一位    bool ervis;//为了标记是不是要赋值为0    bool vis;//标记是否出现过这种字母    int a[100000+10];} t[26+10];bool cmp(pp u,pp v){    for(int i=len-1; i>=0; i--)//从高位到低位,逐次比较    {        if(u.a[i]>v.a[i])            return 1;        else if(u.a[i]<v.a[i])            return 0;    }    return 0;}int main(){    int n,cases=1;    while(~scanf("%d",&n))    {        getchar();        memset(t,0,sizeof(t));        len=0;        for(int i=1; i<=n; i++)        {            scanf("%s",s);            int les=strlen(s);            t[s[0]-'a'].index=1;            for(int j=les-1; j>=0; j--)            {                int x=s[j]-'a';                if(t[x].vis!=1) t[x].vis=1;                     t[x].a[les-j-1]++;            }            len=max(les,len);//为了使长度一致,选最大的        }        for(int i=0; i<26; i++)        {            for(int j=0; j<len-1; j++)            {                if(t[i].a[j]>26)                {                    t[i].a[j+1]+=t[i].a[j]/26;//为了防止出现100 0 和0 1这种情况,先进行字母数量的26进制进位                    t[i].a[j]%=26;                }            }        }        sort(t,t+26,cmp);        bool flag=0;//为了判断是否需要给字母赋上0        for(int i=25; i>=0; i--)        {            if(!t[i].vis)            {                flag=1;                break;            }        }        if(!flag)//需要的话,就从后往前找没有出现在字符串首位的字母        {            for(int i=25; i>=0; i--)            {                if(!t[i].index)                {                    t[i].ervis=1;                    break;                }            }        }        printf("Case #%d: ",cases++);        LL sum=0;        int res=25;        for(int i=0; i<26; i++)        {            if(t[i].vis&&!t[i].ervis)            {                LL tmp=1;                for(int j=0; j<len; j++)                {                    if(t[i].a[j])                        sum=(sum+tmp*t[i].a[j]*res)%mod;                    tmp=(tmp*26)%mod;                }                res--;            }        }        printf("%lld\n",sum);    }}
原创粉丝点击