您的位置:首页 > 其它

HDU 6034(模拟)

2018-03-26 14:28 267 查看
给出n个只包含小写字母的串,分别给其中出现的字母赋值,以26进制赋值(1-25),不同字母只能是不同的值,且不能出现前导0,问所有串所能获得最大权值和

一个O(26*1e6)的复杂度,按位算贡献,把低位的进到高位,然后按高位排序,出现前导零就与他前面一个字母交换权值

(死于前导0去除单个串的情况)

#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <cstring>
#include <vector>
#include <set>
#include <cmath>
#include <map>
#include <sstream>
#define LL long long
#define INF 0x3f3f3f3f
#define mod 1000000007
const int maxn = 100000+5;
using namespace std;
bool vis[maxn];
string s[maxn];
LL k[maxn];
int num[30];
struct node{
int sum[maxn];
int id;
bool operator < (const node &p) const{
for(int i=100000; i>=0; i--){
if(sum[i] != p.sum[i])
return sum[i] > p.sum[i];
}
return 0;
}
}ch[30];
void init(){
for(int i=0; i<26;
4000
i++)
ch[i].id = i;
for(int i=0; i<26; i++){
memset(ch[i].sum, 0, sizeof(ch[i].sum));
}
memset(vis, false, sizeof(vis));
}
int main(){
int n, kases = 1;
k[0] = 1;
for(int i=1; i<=maxn; i++)
k[i] = k[i-1] * 26 % mod;
while(cin >> n){
init();
LL ans = 0;
for(int i=0; i<n; i++){
cin >> s[i];
int len = (int)s[i].length();
for(int j=0; j<len; j++){
if(j == 0 && len > 1)//前导0
vis[s[i][j]-'a'] = true;
int id = s[i][j]-'a';
ch[id].sum[len-j-1]++;//计算贡献
}
}
for(int i=0; i<26; i++){
for(int j=0; j<100000; j++){//贡献从低位往上进
int sum = ch[i].sum[j];
int k = sum / 26;
ch[i].sum[j] %= 26;
ch[i].sum[j+1] += k;
}
}
sort(ch,ch+26);
for(int i=0; i<26; i++){
num[ch[i].id] = 25-i;
}
int pos = 25;
while(true){
if(vis[ch[pos].id]){// 当这个数会成为前导零时
swap(num[ch[pos].id],num[ch[pos-1].id]);
}
else break;
pos--;
}
for(int i=0; i<n; i++){
int len = (int)s[i].length();
for(int j=0; j<len; j++)
ans = (ans + num[s[i][j]-'a']*k[len-1-j] % mod) % mod;
}
cout << "Case #" << kases++ << ": " << ans << endl;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: