1493 C. K-beautiful Strings(从后往前贪心[官方题解])
发布日期:2021-06-30 10:30:24 浏览次数:2 分类:技术文章

本文共 1244 字,大约阅读时间需要 4 分钟。

转自官方题解

我们最好的答案是和原串 s s s相等

如果达不到,就看一下前 n − 1 n-1 n1个字母是否能相等,如果还达不到就看一下前 n − 2 n-2 n2个字母能不能相等…

于是我们从后往前枚举第 k k k个位置,判断 [ 1 , k − 1 ] [1,k-1] [1,k1]和原串相等,在第 k k k个位置大于原串是否可行

基于这个贪心准则,我们计算一个 c n t [ i ] cnt[i] cnt[i]表示 [ 1 , k − 1 ] [1,k-1] [1,k1]中字母 i i i的出现次数

然后计算一个 s u m sum sum表示如果 [ 1 , k − 1 ] [1,k-1] [1,k1]和原串相等,最少需要补齐多少个字母变成 k k k的倍数

s u m = ∑ i = 0 25 ( k − c n t [ i ] % k ) % k sum=\sum\limits_{i=0}^{25}(k-cnt[i]\%k)\%k sum=i=025(kcnt[i]%k)%k

但是第 k k k位比原串大,但是具体放哪个字母呢??

我们可以把这个字母贪心的从 s [ k ] + 1 s[k]+1 s[k]+1枚举到 ′ z ′ 'z' z,看最好能放哪个字母

在第 k k k位放字母 w w w,显然需要更新 s u m sum sum,此时如果 i + s u m < = n i+sum<=n i+sum<=n说明是可行的

因为第 k k k位比较大,已经保证了字典序比较大,后续只需要满足字母是 k k k的倍数即可

没有填满的部分全部填 ′ a ′ 'a' a即可

因为n是k的倍数,前面填充的部分用sum补齐了,所以也是k的倍数。

那么剩下的部分也一定是k的倍数,所以贪心放a没有问题

#include 
using namespace std;const int maxn = 3e5+10;int cnt[27],n,k;string s;int get(int x){
return (k-x%k)%k; }int main(){
int t; cin >> t; while( t-- ) {
cin >> n >> k >> s; for(int i=0;i
=0;i--) {
sum = sum-get( cnt[s[i]-'a'] )+get( --cnt[s[i]-'a'] ); for(int j=s[i]-'a'+1;j<=25;j++)//枚举放哪个字母 {
int las = sum; sum = sum-get( cnt[j] )+get( ++cnt[j] ); if( (i+1)+sum<=n ) {
for(int pos=0;pos

转载地址:https://issue-is-vegetable.blog.csdn.net/article/details/114481976 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:1493 D. GCD of an Array(map+multiset应用)
下一篇:1493 A. Anti-knapsack(思维,构造)

发表评论

最新留言

网站不错 人气很旺了 加油
[***.192.178.218]2024年04月30日 13时00分06秒