• CF1620C BAString题解


    先考虑如何构造一个比序列 \(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;
    }
    
  • 相关阅读:
    博弈论进阶之树的删边游戏与无向图的删边游戏
    博弈论进阶之Every-SG
    HDU 3595 GG and MM(Every-SG)
    博弈论入门之斐波那契博弈
    博弈论入门之威佐夫博弈
    博弈论进阶之Multi-SG
    博弈论进阶之Anti-SG游戏与SJ定理
    博弈论进阶之SG函数
    【每天一个Linux命令】12. Linux中which命令的用法
    《数学之美》之悟——学懂数学为何如此重要?
  • 原文地址:https://www.cnblogs.com/caijiLYC/p/15729909.html
Copyright © 2020-2023  润新知