2022江苏省赛 K. aaaaaaaaaaA heH heH nuN (构造题)
题意: nunhehheh为前缀, x个a为后缀(x >= 1)的字符串称为目标串,构造出只含小写字母的字符串使得恰好含k个子序列为目标串
思路: 答案串的前缀固定为nunhehhe,对于后面的一个h,若这个h后面有x个a,则以这个h做最后一个h的贡献为 \(2^x\)-1。 容易想到利用k的二进位来构造:
- 若k的第pos位为1,则一个h后面需要有pos个a。
- 这样得到的串的贡献是 k - cnt (cnt为k的二进制位为1的个数)
- 这个cnt只需在最后一个a前面多加cnt个h就凑上了。
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false) ,cin.tie(0), cout.tie(0);
//#pragma GCC optimize(3,"Ofast","inline")
#define ll long long
#define PII pair<int, char>
//#define int long long
const int N = 1e6 + 5;
const int M = 1e5 + 5;
const int INF = 0x3f3f3f3f;
const ll LNF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double PI = acos(-1.0);
void solve() {
int n; cin >> n;
if( n == 0 ) {
cout << "apex" << '\n'; return;
}
if( n == 1 ) {
cout << "nunhehheha" << '\n'; return;
}
string ss = "";
vector<int> ve;
int cnt = 0;
for ( int i = 1; i <= 30; ++ i) { //为了方便,从1位开始
if( n & (1 << i) ) ve.push_back(i - 1), ++ cnt;
}
if( n & 1 ) ++ cnt;
int pre = 0; bool f = 1;
for ( auto i : ve ) {
for ( int j = 1; j <= i - pre; ++ j ) {
ss += "a";
}
ss +="h";
pre = i;
}
reverse(ss.begin(), ss.end());
for ( int j = 1; j <= cnt; ++ j ) ss += "h"; ss += "a";
cout << "nunhehhe" + ss << '\n';
}
int main () {
IOS
int t; cin >> t;
while( t -- ) solve();
return 0;
}