题意:给出n个字符串,每个字母可以代表0--25,问这些数字最大的26进制和是多少,不能有前导0,不同字母代表不同数字
思路:每个字符对答案的贡献都可以看作一个 26 进制的数字,问题相当于要给这些贡献加一个 0 到 25 的权重使得答案最大。最大的数匹配 25,次大的数匹配 24,依次类推。排序后这样依次贪心即可,唯一注 意的是不能出现前导 0。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=1e5+1010; 5 const ll mod=1e9+7; 6 7 char a[N]; 8 int b[N][30],vis[30]; 9 struct node{ 10 string s; 11 int id; 12 }d[30]; 13 bool cmp(node p,node q){ 14 if(p.s.size()==q.s.size()) return p.s<q.s; 15 return p.s.size()<q.s.size(); 16 } 17 int main(){ 18 int n; 19 int k=1; 20 while(scanf("%d",&n)!=EOF){ 21 memset(vis,0,sizeof(vis)); 22 memset(b,0,sizeof(b)); 23 for(int i=1;i<=n;i++){ 24 scanf("%s",a+1); 25 if(strlen(a+1)>1) vis[a[1]-'a']=1; 26 int x=0; 27 for(int j=strlen(a+1);j>=1;j--){ 28 b[x++][a[j]-'a']++; 29 } 30 } 31 for(int i=0;i<26;i++){//每个字母的26进制规范// 32 for(int j=0;j<=10100;j++){ 33 if(b[j][i]>=26){ 34 b[j+1][i]+=b[j][i]/26; 35 b[j][i]%=26; 36 } 37 } 38 } 39 for(int i=0;i<26;i++){ 40 d[i].id=i; 41 d[i].s=""; 42 for(int j=100100;j>=0;j--){ 43 if(b[j][i]){ 44 for(int kk=j;kk>=0;kk--){ 45 d[i].s+=(char)(b[kk][i]+'0'); 46 } 47 break; 48 } 49 } 50 } 51 int now; 52 sort(d,d+26,cmp); 53 54 for(int i=0;i<26;i++){ 55 if(vis[d[i].id]==0) {now=i;break;} 56 } 57 58 ll ss=1; 59 ll sum=0; 60 for(int i=0;i<26;i++){ 61 if(i==now) {continue;} 62 ll kk=1; 63 ll ssum=0; 64 for(int j=0;j<=100100;j++){ 65 ssum=(ssum+(1LL*b[j][d[i].id])*kk)%mod; 66 kk=(kk*26)%mod; 67 } 68 sum=(sum+ssum*ss+mod)%mod; 69 ss++; 70 } 71 printf("Case #%d: ",k++); 72 cout<<sum<<endl; 73 } 74 return 0; 75 }