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;
}
posted @ 2021-12-25 10:04  蒟蒻丁  阅读(87)  评论(0编辑  收藏  举报