2017 Multi-University Training Contest - Team 1 Balala Power!

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Jane_JXR/article/details/76106313

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6034

题目大意:n个字符串,每个字符串都相当于一个26进制的数,把a~z分配0~25的权值,使所有的字符串的26进制数之和最大,答案对1e9+7取模。


分析:相同字母在相同位置对答案的贡献相同,我们可以预处理所有字符串,记录每个字母在每个位置出现的次数。
1、可以把字母a~z所对应的所有贡献看成一个字符串或double型数字
2、贪心赋权值,把贡献大的赋的权值更大,注意前导0的处理


当把贡献看成字符串时,需要注意每个字符串每位上的值不能大于25,即需要进位处理。
当看成double型数字时,我们可以把结果直接转化到最大的那位,比较大小即可。(这样更方便处理)


CODE1:转化为double型数字

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#include<stack>
#include<math.h>
#include<map>
#include<iostream>
#define INF 0x3f3f3f3f
typedef  long long LL;
using namespace std;
const int maxn=100005;
const int mod=1e9+7;
double dp[maxn][30];
char str[maxn];
int vis[30],mp[30],a[maxn];
vector<string>v;
struct node
{
    int id;
    double x;
}p[30];
bool cmp(node aa,node bb)
{
    return aa.x>bb.x;
}
int main()
{
    int n,T=0;
    while(~scanf("%d",&n))
    {
        v.clear();
        int lmax=0;
        memset(dp,0,sizeof(dp));
        memset(vis,0,sizeof(vis));
        memset(mp,0,sizeof(mp));
        for(int i=0;i<n;i++)
        {
            scanf("%s",str);
            vis[str[0]-'a']=1;
            int len=strlen(str);
            a[i]=len;
            lmax=max(len,lmax);
            v.push_back(str);
            for(int j=0;j<len;j++)
            dp[len-j-1][str[j]-'a']++;
        }
        for(int i=0;i<=lmax;i++)
        {
            for(int j=0;j<26;j++)
            {
            dp[i][j]+=(dp[i-1][j]/26);
               // cout<<dp[i][j]<<" ";
            }
           // cout<<endl;
        }
        for(int i=0;i<26;i++)
            p[i].id=i,p[i].x=dp[lmax][i];
        sort(p,p+26,cmp);
        for(int i=0;i<26;i++)//贪心赋权值
            mp[p[i].id]=25-i;
        int k=25;
        while(vis[p[k].id])//保证原字符串无前导0
        {
            swap(mp[p[k].id],mp[p[k-1].id]);
            k--;
        }
//        for(int i=0;i<26;i++)
//            cout<<mp[i]<<" ";
        LL sum=0;
        int m=v.size();
        for(int i=0;i<m;i++)
        {
            LL ans=0;
            for(int j=0;j<a[i];j++)
            {
                ans=(ans*26+mp[v[i][j]-'a'])%mod;
            }
            sum=(sum+ans)%mod;
        }
        printf("Case #%d: %lld\n",++T,sum);
    }
}


CODE2:转化为字符串

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#include<stack>
#include<math.h>
#include<map>
#include<iostream>
#define INF 0x3f3f3f3f
typedef  long long LL;
using namespace std;
const int maxn=100005;
const int mod=1e9+7;
int dp[maxn][30];
char str[maxn];
int vis[30],mp[30],a[maxn];
vector<string>v;
struct node
{
    int id;
    string s;
    node()
    {
        s="\0";
    }
} p[30];
bool cmp(node aa,node bb)
{
    int len1=aa.s.size();
    int len2=bb.s.size();
    if(len1==len2)
    {
       return aa.s+bb.s>bb.s+aa.s;
    }
    return len1>len2;
}
LL POW(int x)
{
    LL sum=1;
    LL y=26;
    while(x)
    {
        if(x&1)
            sum=(sum*y)%mod;
        y=(y*y)%mod;
        x>>=1;
    }
    return sum;
}
int main()
{
    int n,T=0;
    while(~scanf("%d",&n))
    {
        v.clear();
        int lmax=0;
        memset(dp,0,sizeof(dp));
        memset(vis,0,sizeof(vis));
        memset(mp,0,sizeof(mp));
        for(int i=0; i<n; i++)
        {
            scanf("%s",str);
            vis[str[0]-'a']=1;
            int len=strlen(str);
            a[i]=len;
            lmax=max(len,lmax);
            v.push_back(str);
            for(int j=0; j<len; j++)
                dp[len-j-1][str[j]-'a']++;
        }
        for(int j=0; j<26; j++)
        {
         for(int i=0; i<lmax; i++)
            {
                if(dp[i][j]>=26)
                {
                    dp[i+1][j]+=dp[i][j]/26;
                    dp[i][j]=dp[i][j]%26;
                }
            }
        }
//        for(int i=0;i<lmax;i++)
//        {
//            for(int j=0;j<26;j++)
//                 cout<<dp[i][j]<<" ";
//                 cout<<endl;
//        }
        for(int i=0; i<26; i++)
        {
            p[i].s="\0";
            for(int j=0; j<=lmax; j++)
            {
                p[i].id=i;
                p[i].s+=dp[j][i]+'a';
            }
            reverse(p[i].s.begin(),p[i].s.end());
        }
        sort(p,p+26,cmp);
        for(int i=0; i<26; i++) //贪心赋权值
            mp[p[i].id]=25-i;
        int k=25;
        while(vis[p[k].id])//保证原字符串无前导0
        {
            swap(mp[p[k].id],mp[p[k-1].id]);
            k--;
        }
//        for(int i=0;i<26;i++)
//        {
//          // cout<<p[i].s<<endl;
//           cout<<mp[i]<<" ";
//        }
        LL sum=0;
        int m=v.size();
        for(int i=0; i<m; i++)
        {
            LL ans=0;
            for(int j=0; j<a[i]; j++)
            {
                 ans+=(POW(a[i]-j-1)*mp[v[i][j]-'a'])%mod;
                    sum%=mod;
               // cout<<ans<<" ";
            }
          //  cout<<endl;
            sum=(sum+ans)%mod;
        }
        printf("Case #%d: %lld\n",++T,sum);
    }
}


Balala Power!

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 2221    Accepted Submission(s): 422


Problem Description

Talented  Mr.Tang has  n strings consisting of only lower case characters. He wants to charge them with Balala Power (he could change each character ranged from  a to  z into each number ranged from  0 to  25, but each two different characters should not be changed into the same number) so that he could calculate the sum of these strings as integers in base  26 hilariously.

Mr.Tang wants you to maximize the summation. Notice that no string in this problem could have leading zeros except for string "0". It is guaranteed that at least one character does not appear at the beginning of any string.

The summation may be quite large, so you should output it in modulo  109+7.
 

Input
The input contains multiple test cases.

For each test case, the first line contains one positive integers  n, the number of strings.  (1n100000)

Each of the next  n lines contains a string  si consisting of only lower case letters.  (1|si|100000,|si|106)
 

Output
For each test case, output " Case #xy" in one line (without quotes), where  x indicates the case number starting from  1 and  y denotes the answer of corresponding case.
 

Sample Input
 
  
1 a 2 aa bb 3 a ba abc
 

Sample Output
 
  
Case #1: 25 Case #2: 1323 Case #3: 18221
 

Source



猜你喜欢

转载自blog.csdn.net/Jane_JXR/article/details/76106313