很烦的一道题,当时比赛的时候wa了9次,TLE了10+次,还是没过;
第一种思路是将所有的字母都化为到个位,然后一边取模,在打表之后时间够了,但是一直wa,也没找到错的地方;
第二种思路是用26个字符串固定26个字母,就是考虑进位的地方有点繁琐,但一直TLE;
最后时间到了。。
在补题的时候,就试着用数组代替字符串,然后重复操作,再做到找到最小的可做0的一位做0,还是选择 C++ 提交还是TLE,后来同样的代码改了G++就过了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
const int maxn = 1e5+5;
ll fac[maxn] = {1};
int Hash[27];
bool lead[27];
char str[maxn];
void init()
{
for(int i = 1; i < maxn; i++)
fac[i] = fac[i-1]*26%mod;
}
struct node
{
int cnt[maxn];
int id;
bool operator < (const node &a) const
{
for(int i = maxn-1; i >= 0; i--)
{
if(cnt[i] > a.cnt[i]) return 1;
else if(cnt[i] < a.cnt[i]) return 0;
else ;
}
}
}a[27];
int main(void)
{
int n, ca = 1;
init();
while(~scanf("%d", &n))
{
memset(a, 0, sizeof(a));
memset(Hash, -1, sizeof(Hash));
memset(lead, 0, sizeof(lead));
for(int i = 1; i <= n; i++)
{
scanf(" %s", str);
int len = strlen(str);
if(len != 1)
lead[str[0]-'a'] = 1;
for(int i = 0; i < len; i++)
a[str[i]-'a'].cnt[len-i-1]++;
}
//进位操作,满26个等与一个下一位
for(int i = 0; i < 26; i++)
{
for(int j = 0; j < maxn; j++)
{
if(a[i].cnt[j] >= 26)
{
a[i].cnt[j+1] += a[i].cnt[j]/26;
a[i].cnt[j] %= 26;
}
}
a[i].id = i;
}
sort(a, a+26);
for(int i = 0; i < 26; i++)
Hash[a[i].id] = 26-i-1;
for(int i = 0; i < 26; i++) //前导0找最小的可以做0的位来放0
if(lead[a[i].id] && Hash[a[i].id] == 0)
{
for(int j = 25; j >= 0; j--)
{
if(!lead[a[j].id])
{
for(int k = 25; k >= j+1; k--)
Hash[a[k].id] = Hash[a[k-1].id];
Hash[a[j].id] = 0;
break;
}
}
break;
}
ll ans = 0;
for(int i = 0; i < 26; i++)
{
for(int j = 0; j < maxn; j++)
{
ans = (ans+fac[j]*a[i].cnt[j]*Hash[a[i].id]%mod)%mod;
}
}
printf("Case #%d: %lld\n", ca++, ans);
}
return 0;
}
看来还是太年轻。。如果TLE就G++,C++都交一边