专栏文章

题解:AT_nikkei2019ex_g 回文スコア

AT_nikkei2019ex_g题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@miq06p1u
此快照首次捕获于
2025/12/03 20:48
3 个月前
此快照最后确认于
2025/12/03 20:48
3 个月前
查看原文

题意

给你若干个字符,从中选择字符组成若干个回文串,每个回文串 ii 的得分是 leni2{len_i}^2,求最大的 leni\sum len_i

思路

考虑贪心。
由于 leni2{len_i}^2 随长度 leni{len_i} 增长很快,优先构造尽可能长的回文串是合理的。
可以在一开始先记录每个字符出现的次数,每一次构造回文串,对于每个字符,都有以下两种情况:
  • 个数是奇数,如果当前串是空的,全部填进去(中心的字符可以是 11 个),如果当前串不空,就留下一个。
  • 个数是偶数,全部填进去。
记录个数 resres,每次 ansans 累加 res2res^2 即可。
时间复杂度 O(len)O(len)

Code

CPP
#include<bits/stdc++.h>
#define int long long
#define double long double
#define bug cout<<"___songge888___"<<'\n';
using namespace std;
string s;
int cnt[55];
int check(){
    for(int i=1;i<=26;i++){
        if(cnt[i]){
            return 1;
        }
        
    }
    return 0;
}
int len;
int ans;
signed main() {
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin>>s;
    len=s.size();
    for(int i=0;i<len;i++){
        cnt[s[i]-'a'+1]++;
    }
    while(check()){
        int flag=0;
        int res=0;
        for(int i=1;i<=26;i++){
            if(cnt[i]%2){
                if(flag){
                    res+=cnt[i]-1;
                    cnt[i]=1;
                }
                else{
                    flag=1;
                    res+=cnt[i];
                    cnt[i]=0;
                }
            }
            else{
                res+=cnt[i];
                cnt[i]=0;
            }
        }
        ans+=res*res;
    }
    cout<<ans;
    return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...