CF1620C BA-String题解
先考虑如何构造一个比序列 \(A\) ,字典序大一的序列
首先考虑在末尾添加一个 \(b\) ,如果超过了添加上限,那么就进一位。把末尾的 \(b\) ,全部拿掉,然后在前面一个可以放置 \(b\) 的地方放一个,比如下面情况
3 2 3
a * a *
a a
a a b
a b a
于是我们可以理解为找一个字典序为 \(k\) ,的序列就是找到 \(k\) 在不定进制下的表达,考虑倒序枚举,首先找到第一个开始放置 \(b\) 的位置在哪里,然后从这里开始找
每次用 \(k'\) 取模后面的总方案数,就能知道当前的位置要放置多少个 \(b\) ,以此类推即可构造出答案
#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
ll n,m,k,a[1000010],f[1000101],ans[1000011],T,p;
char c[10001];
int main(){
cin>>T;
while(T--){
memset(a,0,sizeof(a));
memset(f,0,sizeof(f));
memset(ans,0,sizeof(ans));
scanf("%lld%lld%lld",&n,&m,&k);
p=0,n++;
scanf("%s",c+2);
c[1]='a';
for(ll i=1;i<=n;i++)
if(c[i]=='a')p++;
ll r=p,num=0,pos=-1;
for(ll i=n;i>=1;i--){
if(c[i]=='a')
a[r--]=num,num=0;
else num++;
}
for(ll i=1;i<=p;i++)a[i]*=m;
for(ll i=1;i<=p;i++)a[i]++;
f[p]=a[p];
for(ll i=p;i>=1;i--){
if(!f[i])f[i]=f[i+1]*a[i];
if(f[i]<0)f[i]=1e18;
if(f[i]>=k){
pos=i;
break;
}
}
f[p+1]=1;
for(ll i=pos;i<=p&&k;i++){
if(k%f[i+1]==0)ans[i]=k/f[i+1]-1;
else ans[i]=k/f[i+1];
k-=f[i+1]*ans[i];
}
for(ll i=1;i<=p;i++){
if(i!=1)printf("a");
for(ll j=1;j<=ans[i];j++)printf("b");
}
puts("");
}
return 0;
}