杭电多校 1002 Balala Power! 题解报告
2017-07-26 14:03
274 查看
题目意思不太好理解
大致说一下
小写字母a-z 中的任何一个字母可以用0-25中的任何一个数字表示
但是每个数字只能对应一个字母
解释一下样例
输入一个数 表示下面会输入几个字符串
然后输入字符串 比如aa bb
a b可以用0-25中的任何一个数字表示 但是 是一个26进制的数
但是要让这个数最大
——26进制转换为10进制的方法——
—1.先看这个26进制的数有多少位 比如123 有三位
—2.然后1*26^2 + 2*26^1 + 3*26^0 = 1*26*26+2*26+3 = 731;
然后a取25 b只能取26
这样aa就是 25*26+25 = 675;
bb就是 24*26+24 = 648;
最后648+675 = 1323;
不知道有没有解释清楚 这题还是大三的学长和我讲解的题意
要注意的就是 0-25任意一个数表示一个字母的时候 是一个26进制的数字 要转换为10进制的数字
所以要做出相应的转换
还有一个前导0的问题 题目要求说 不能有第一个是0的排序 注意
这是思路:
上代码
#include <cstdio> #include <cmath> #include <vector> #include <iostream> #include <set> #include <queue> #include <cstring> #include <algorithm> using namespace std; #define mst(a,b) memset((a),(b),sizeof(a)) // define the reset method #define rush() int T;scanf("%d",&T);while(T--) // define the case statistics method typedef long long ll; const int maxn = 100 4000 005; const ll mod = 1e9+7; const int INF = 0x3f3f3f; const double eps = 1e-9; int n; char s[maxn]; int num[26][maxn]; int vis[26]; int val[maxn]; ll po[maxn]; int Max; struct node // { char xx[maxn]; // deposit the string a-z int id; }e[26]; bool cmp(const node &a,const node &b) //对贡献从大到小排序 { for(int i=Max-1; i>=0; i--) // Max the lenght of the string { if(a.xx[i]>b.xx[i]) return 1; if(a.xx[i]<b.xx[i]) return 0; } return 1; } void init() //预处理26^n%mod { po[0]=1; for(int i=1; i<maxn; i++) { po[i]=(po[i-1]*26)%mod; } } int main() { //freopen("input.txt","r",stdin); //freopen("output.txt","w",stdout); int n; int cas=1; init(); while(~scanf("%d",&n)) { mst(num,0); mst(vis,0); mst(val,0); for(int i=0; i<n; i++) { scanf("%s",s); int len=strlen(s); if(len>1) //标记这个字母权值不能为零 { vis[s[0]-'a']=1; // one point get } for(int j=len-1; j>=0; j--) //统计每个字母在第几位上有几个 { int o=len-1-j; num[s[j]-'a'][o]++; } Max=max(Max,len); //减少循环,节约时间 } for(int i=0; i<26; i++) { for(int j=0; j<maxn; j++) { if(num[i][j]>=26&&j!=Max-1) //number big than 26,we need to exceed; { num[i][j+1]+=num[i][j]/26; // ? num[i][j]%=26; // exceed } } } for(int i=0; i<26; i++) { for(int j=0; j<Max; j++) { e[i].xx[j]=num[i][j]+'a'; //转化为字符形式,节约内存,如果是int可能会爆内存 } e[i].id=i; } sort(e,e+26,cmp); int pos=-1; for(int i=25;i>=0;i--) //从权值小的开始找权值可以为0的字母 { if(vis[e[i].id]==0) { pos=e[i].id; // sign the e[i].id == 0 break; } } int flag=0; for(int i=0;i<26;i++) //给每个字母附上权值 { if(e[i].id==pos) { val[e[i].id]=0; flag=1; continue; } if(flag==0) //We have sorted the array. val[e[i].id]=25-i; else val[e[i].id]=25-i+1; } ll ans=0; for(int i=0;i<26;i++) { for(int j=0;j<Max;j++) { if(num[i][j]) { ll temp=(ll)num[i][j]*val[i]*po[j]%mod; ans=(ans+temp)%mod; } } } printf("Case #%d: %I64d\n",cas++,ans); } return 0; }
然后晚一点 我会再回来讲解一下这个代码
先说这么多
代码更新了一下
代码是从这个博客转过来的http://blog.csdn.net/my_sunshine26/article/details/76098497
这一题的思路是要按照字母对26进制数的贡献值进行排序 然后按照排序依次从25开始赋值
统计出每个字母在哪一位出现了几次,然后比较每个字母取能对结果产生的贡献大小。
每个字母从最后一位开始,如果个数大于等于26,则向前进位,以此类推,最终只要从最高位的个数开始比较即可。注意要考虑前导 0
解释一下:为什么如果个数大于等于26,则向前进位
因为26进制数 如果有字幕的个数大于26的话乘不了26^26 所以这里要进位处理。
相关文章推荐
- 2017 杭电多校联赛 1002 Balala Power!(数字替换字母)HDU 6034
- 2017 Multi-University Training Contest - Team 1 1002 Balala Power!(贪心)
- 17 多校 - 1 - 1002 - Balala Power! (HDU 6034)
- 2017 Multi-University Training Contest - Team 1 1002 Balala Power!
- HDU_【2017 Multi-University Training Contest 1】——1002.Balala Power!
- 2017 Multi-University Training Contest - Team 1 :1002:Balala Power!
- 1002 Balala Power!
- 2017 Multi-University Training Contest 1 1002. Balala Power!(贪心)
- 杭电OJ题 1002 A + B Problem II 解题报告
- codevs 1002 搭桥 题解报告
- 2017 多校训练 1002 Balala Power!
- HDU 2017 多校联合训练赛1 1002 6034 Balala Power 排序
- 杭电 1425 sort 题解报告
- 2017 Multi-University Training Contest - Team 1 1002&&HDU 6034 Balala Power!【字符串,贪心+排序】
- 2017 Multi-University Training Contest - Team 1 1002 Balala Power!
- 杭电 1071 The area 题解报告
- 2017 Multi-University Training Contest - Team 1:1002 Balala Power!
- 杭电 1418 抱歉 题解报告
- 【2017 Multi-University Training Contest - Team 1 1002】Balala Power!
- 杭电多校 1001 Add More Zero 题解报告