https://codeforces.com/contest/1493/problem/C
当时没做出来的div2C,那天打cf太上头了
感觉冷静下来仔细分清楚情况想清楚也没那么难
因为要>=s且满足条件,所以从后往前枚举分界线,左边相等b[i]=s[i],当前位置b[i]>s[i],后面随意
然后我们可以根据左边剩余的字母算出让他们出现时k的倍数最少需要添加多少个,扫一遍26就算出来了
然后两种情况,第一种情况需要添加的数量刚好等于分界线后面的位置数量,那么就直接看有没有一个b[i]>s[i]的填就行了,接下来的就从小搞到大
如果需要的数量<有的数量,说明至少多出了k个可以用来乱放,那么只要s[i]!='z',就让b[i]=s[i]+1就行了,接下来就让26个字母填满,多出的全填字母a
#include<bits/stdc++.h>
using namespace std;
const int maxl=1e5+10;
int n,k,ans;
int a[maxl];
char s[maxl],b[maxl];
inline void prework()
{
scanf("%d%d",&n,&k);
scanf("%s",s+1);
for(int i=0;i<26;i++)
a[i]=0;
for(int i=1;i<=n;i++)
a[s[i]-'a']++;
for(int i=0;i<26;i++)
a[i]%=k;
}
inline int calc()
{
int sum=0;
for(int i=0;i<26;i++)
if(a[i]>0)
sum+=k-a[i];
return sum;
}
inline int jug(int x)
{
for(int i=x+1;i<26;i++)
if(a[i]>0)
return i;
return 0;
}
inline void mainwork()
{
ans=-1;
if(n%k!=0)
return;
if(calc()==0)
{
ans=1;
for(int i=1;i<=n;i++)
b[i]=s[i];
return;
}
for(int i=n;i>=1 && ans<0;i--)
{
a[s[i]-'a']=(a[s[i]-'a']-1+k)%k;
if(s[i]=='z')
continue;
if(calc()==n-i+1&&jug(s[i]-'a')>0)
{
ans=1;
for(int j=1;j<i;j++)
b[j]=s[j];
int big=jug(s[i]-'a');
b[i]=big+'a';
a[big]=(a[big]+1)%k;
int now=i;
for(int j=0;j<26;j++)
while(a[j]!=0)
b[++now]=j+'a',a[j]=(a[j]+1)%k;
}
else if(calc()<n-i+1)
{
ans=1;
for(int j=1;j<i;j++)
b[j]=s[j];
b[i]=s[i]+1;
a[b[i]-'a']=(a[b[i]-'a']+1)%k;
int now=i;
for(int j=0;j<26;j++)
while(a[j]!=0)
b[++now]=j+'a',a[j]=(a[j]+1)%k;
while(now<n)
b[++now]='a';
sort(b+i+1,b+n+1);
}
}
}
inline void print()
{
if(ans<0)
puts("-1");
else
{
for(int i=1;i<=n;i++)
printf("%c",b[i]);
puts("");
}
}
int main()
{
int t;
scanf("%d",&t);
for(int i=1;i<=t;i++)
{
prework();
mainwork();
print();
}
return 0;
}