BA-String (思维构造,进制转换)

C. BA-String

[Link](Problem - C - Codeforces)

题意

给你一个字符串(只含 a , ∗ a,* a,), 将其中的 ∗ * 替换成 [ 0 , k ] [0,k] [0,k] b b b,问你所有情况中字典序第 x x x小的是什么。

思路

​ 对于连续的 ∗ * 我们可以随便填假设有 c n t cnt cnt个我们一共有 k × c n t + 1 k\times cnt + 1 k×cnt+1种填法,对于连续的 a a a也是没有用的因为 a a a只是相当于一个间隔符。连续的 ∗ * 对字典序的贡献并不是 k × c n t + 1 k\times cnt+1 k×cnt+1

​ 看个例子 ∗ a ∗ ∗ , k = 1 *a**,k=1 a,k=1,它的子集有 a , a b , a b b , b a , b a b , b a b b a,ab,abb,ba,bab,babb a,ab,abb,ba,bab,babb,我们先对的 x x x 1 1 1保证填从 1 1 1开始。对于 a a a左边的 ∗ * 来说每填一个 b b b都要算上这个间隔 a a a右面的 ∗ * 对他的贡献, b a ba ba并不是 1 1 1而是 1 + 3 1 + 3 1+3。也就是当前需要附加上前面的 ∗ * 对它的贡献,对于每一个连续的 c n t 个 ∗ cnt个* cnt我们可以看成一个 c n t cnt cnt进制,类比于我们的十进制,最终要变成 x 1 + x 2 × c n t 1 + x 3 × c n t 1 × c n t 2 + . . . + x k × c n t 1 × . . . × c n t k − 1 = = x − 1 x_1 +x_2\times cnt_1 +x_3\times cnt_1\times cnt_2+...+x_k\times cnt_1\times ...\times cnt_{k-1}==x-1 x1+x2×cnt1+x3×cnt1×cnt2+...+xk×cnt1×...×cntk1==x1

类似于十进制转二进制,我们不断的找到当前连续的 ∗ * 是多少进制,然后先 m o d mod mod找到这一位的余数再 ÷ \div ÷剩下的进位(剩下的等价于乘了 c n t 1 × c n t 2 . . . cnt_1\times cnt_2... cnt1×cnt2...)。

Code

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <set>
#include <queue>
#include <vector>
#include <map>
#include <bitset>
#include <unordered_map>
#include <cmath> 
#include <stack>
#include <iomanip>
#include <deque> 
#include <sstream>
#define x first
#define y second
#define debug(x) cout<<#x<<":"<<x<<endl;
using namespace std;
typedef long double ld;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef unsigned long long ULL;
const int N = 1e5 + 10, M = 2 * N, INF = 0x3f3f3f3f, mod = 1e9 + 7;
const double eps = 1e-8, pi = acos(-1), inf = 1e20;
#define tpyeinput int
inline char nc() {static char buf[1000000],*p1=buf,*p2=buf;return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;}
inline void read(tpyeinput &sum) {char ch=nc();sum=0;while(!(ch>='0'&&ch<='9')) ch=nc();while(ch>='0'&&ch<='9') sum=(sum<<3)+(sum<<1)+(ch-48),ch=nc();}
int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
int h[N], e[M], ne[M], w[M], idx;
void add(int a, int b, int v = 0) {
	e[idx] = b, w[idx] = v, ne[idx] = h[a], h[a] = idx ++;
}
int n, m, k;
LL x;
int a[N];
int main() {
	ios::sync_with_stdio(false), cin.tie(0);
	int T;
	cin >> T;
	while (T -- ) {
		cin >> n >> k >> x;
		string str;
		cin >> str;
		x --;
		reverse(str.begin(), str.end());
		int cnt = 0; 
		string res;

		for (auto s : str) 
			if (s == 'a') {
				res += string(x % (cnt * k + 1), 'b');
				x /= (cnt * k + 1);					
				res += 'a';
				cnt = 0;
			}
			else cnt ++;
		res += string(x % (cnt * k + 1), 'b');
		reverse(res.begin(), res.end());
		cout << res << endl;
	}
	return 0;
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值