1. 程式人生 > >2017多校 Balala Power!

2017多校 Balala Power!

當時比賽這個題,wa了次,最後發現思路是有一點問題。今天補題,也是出現了很多錯誤,哎,還是太菜了,必須要多寫程式碼。

題意:將a-z這26個字母用0-25進行賦值。那麼對於一個字串,就可以看作是一個26進位制,那麼該字串就可以轉化為一個10進位制的數,求所有字串的和的最大值。(如果一個字母被賦值為0,那麼該字母不能出現在首位。a這種是可以的)

比賽時候的思路是:我把每一個位賦初值0,100000,200000....這種。每個字母出現在每一位的時候就++,然後把所有字母的和相加,可以對這些字母進行排序。

後來想的是通過用num[26][100010],表示該字母在這一位上的個數,如果數量超過26,就進位。

程式碼如下:

//高精度的思想求每個字母的權值 
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
ll num[28][100050];
ll high[27],alph[27],lead[27],weight[27];//high記錄每個字母的最高位是第幾位,alph記錄字母的權值大小,從大到小,lead記錄前導零,weight記錄權值 
bool cmp(ll a,ll b)
{
if(high[a]==high[b])
{
for(ll j=high[a];j>=0;j--)
{
if(num[a][j]!=num[b][j])
  return num[a][j]>num[b][j];
}
}
else
 return high[a]>high[b];
}
long long pow(long long a,long long x)//以防萬一,這裡以後都要有long long 
{
long long res=1;
while(x)
{
if(x&1)
 res=(res*a)%mod;
a=(a*a)%mod;
x>>=1;
}
return res%mod;
}
int main()
{
    ll n,kase=1;
    while(~scanf("%lld",&n))
    {
    char s[100010];
    ll lenn=-1;
    memset(num,0,sizeof(num));
    memset(lead,0,sizeof(lead));
    memset(high,0,sizeof(high));
        for(int i=0;i<n;i++)
        {
        scanf("%s",&s);
   ll len=strlen(s);
   if(len!=1)
     lead[s[0]-'a']=1;
   for(ll j=len-1;j>=0;j--)
   {
   num[s[j]-'a'][len-j]++;
   if(num[s[j]-'a'][len-j]>=26)//1是最低位 
   {
   num[s[j]-'a'][len-j+1]+=num[s[j]-'a'][len-j]/26;
   num[s[j]-'a'][len-j]=num[s[j]-'a'][len-j]%26;
}
}
lenn=max(lenn,len);
}
for(ll i=0;i<26;i++)
{
for(ll j=1;j<lenn+10;j++)
{
if(num[i][j])
  high[i]=j;//記錄每個字母的最高位 
num[i][j+1]+=num[i][j]/26;
num[i][j]=num[i][j]%26;
}

for(ll i=0;i<26;i++)
 alph[i]=i;
sort(alph,alph+26,cmp);
int k=25;
for(int i=0;i<26;i++)
  weight[alph[i]]=k--;
   if(weight[alph[25]]==0&&lead[alph[25]])//如果權值最小的那個字母是首字母 
   {
   for(int i=24;i>=0;i--)
   {
   if(lead[alph[i]]==0)
   {
   for(int j=25;j>=i;j--)
   {
   weight[alph[j]]=weight[alph[j-1]];
}
weight[alph[i]]=0;
break;
}
}
}
long long ans=0;
for(ll i=0;i<26;i++)
{
for(ll j=1;j<lenn+26;j++)
{
ans+=((long long)(pow(26,j-1)*weight[i])%mod*num[i][j])%mod;
ans=ans%mod;
}
}
printf("Case #%lld: %lld\n",kase++,ans);
}
}