hdu6034-贪心&进制-2017多校1-Balala Power!

来源:互联网 发布:截取串口数据代码 编辑:程序博客网 时间:2024/06/17 21:34

http://acm.hdu.edu.cn/showproblem.php?pid=6034
给定一系列字符串,
给每个字母对应的 0-25映射,要求每个串映射的26进制数最大。每个长度大于1的串开头的字母不能映射为0!

思路:先计算每个字母对应的 权值和(比如a出现在第一个串个数位1次,第二个串十数位1次,权值和就是1+26=27)
但是要注意的一点,直接根据权值和从大到小赋值 25-0,是不可以的。
首先是 有 0赋值的限制条件(0映射的字母不能放在第一个串)。
然后是 权值和 在后来会mod,所以直接比较时不可以的。。
所以还要存一个26进制的数组来模拟比较大小。。
题解的排序方法是很好玩的哈哈

#include <bits/stdc++.h>using namespace std;typedef long long ll;const int maxn=1000006;int num[30][maxn];//记录每种字母出现的对应26进制。bool ban[30];//禁止的数。int sum[30];//每种元素出现的权值和。char str[maxn];int a[maxn];//学习一个,用于排序的。const int mod=1000000007;ll wq[maxn];int l;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 init(){     wq[0]=1;   for(int i=1;i<maxn;i++){       wq[i]=(wq[i-1]*26)%mod;       //求位权       }}int w,tt=1;void solve(){            l=0;          memset(num,0,sizeof(num));          memset(sum,0,sizeof(sum));          memset(ban,false,sizeof(ban));          for(int i=0;i<w;i++){                scanf("%s",str);             int len=strlen(str);             if(len>1)                 ban[str[0]-'a']=true;             reverse(str,str+len);             for(int j=0;j<len;j++){                sum[str[j]-'a']+=wq[j];                while(sum[str[j]-'a']>mod)                    sum[str[j]-'a']-=mod;                num[str[j]-'a'][j]++;             }             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]) {//可能l会变大,这样            num[i][l + 1] += num[i][l] / 26;            num[i][l ++] %= 26;        }        a[i] = i;    }          sort(a,a+26,cmp);          long long ans=0;          //弄一弄第一个0;          int zero=-1;          for(int i=25;i>=0;i--){               if(!ban[a[i]])               {zero=a[i];break;}          }          int x=25;          for(int i=0;i<=25;i++){                if(a[i]!=zero)              ans=(ans+(sum[a[i]]*1ll*(x--)))%mod;          }           printf("Case #%d: %lld\n",tt++,ans);}int main(){init();while(~scanf("%d",&w))solve();return 0;}
原创粉丝点击