alg2025/src/8/2/T644759.cpp
2025-08-02 15:58:10 +08:00

152 lines
4.5 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <iostream>
#include <vector>
using namespace std;
typedef long long ll; // 定义长整型别名,用于处理大数
int main() {
ios::sync_with_stdio(false);
cin.tie(0); // 优化输入输出速度
int k;
cin >> k; // 读取数字集合大小
vector<int> d(k); // 存储数字集合
for (int i = 0; i < k; i++) {
cin >> d[i]; // 读取数字集合元素
}
// 检查数字集合是否包含0
bool has_zero = (d[0] == 0);
// 计算首位可用数字数量首位不能为0
int m = has_zero ? k - 1 : k;
// 创建首位可用数字数组
vector<int> arr;
if (has_zero) {
// 如果含0首位使用除0外的其他数字
arr = vector<int>(d.begin() + 1, d.end());
} else {
// 如果不含0所有数字都可用于首位
arr = d;
}
// 存储各长度幸运数的数量
vector<ll> cnt;
// 存储幸运数数量的前缀和
vector<ll> prefix;
ll total = 0; // 累计幸运数总数
int max_len = 0; // 最大长度
// 计算各长度幸运数的数量
for (int len = 1; ; len++) {
ll count_this; // 当前长度的幸运数数量
if (len == 1) {
// 长度为1只有首位数字
count_this = m;
} else {
count_this = m; // 首位有m种选择
// 计算剩余len-1位的组合数
for (int i = 1; i < len; i++) {
// 防止溢出超过10^18时设为极大值
if (count_this > 1000000000000000000LL / k) {
count_this = 1000000000000000001LL;
break;
}
count_this = count_this * k; // 每增加一位数量乘以k
}
// 再次检查溢出
if (count_this > 1000000000000000000LL) {
count_this = 1000000000000000001LL;
}
}
// 更新总数
total += count_this;
// 防止总数溢出
if (total > 1000000000000000000LL) {
total = 1000000000000000001LL;
}
// 存储当前长度数量和前缀和
cnt.push_back(count_this);
prefix.push_back(total);
max_len++; // 增加长度计数
// 当总数超过10^18时停止计算
if (total >= 1000000000000000000LL) {
break;
}
}
int q;
cin >> q; // 读取查询数量
while (q--) {
ll x;
cin >> x; // 读取查询的序号
ll prev = 0; // 存储当前长度之前的所有幸运数数量
int cur_len = -1; // 存储目标幸运数的长度
// 查找目标幸运数所在长度区间
for (int i = 0; i < max_len; i++) {
if (x <= prefix[i]) {
cur_len = i + 1; // 确定长度
break;
}
prev = prefix[i]; // 更新前缀和
}
// 处理极端情况(理论上不会发生)
if (cur_len == -1) {
cur_len = max_len;
prev = prefix.back() - cnt.back();
}
// 计算在当前长度组内的位置
ll pos = x - prev;
int r = cur_len - 1; // 剩余位数(除首位外)
// 计算剩余位数的基数k^(r)
ll base_val = 1;
if (r > 0) {
for (int i = 0; i < r; i++) {
// 防止溢出
if (base_val > 1000000000000000000LL / k) {
base_val = 1000000000000000001LL;
break;
}
base_val = base_val * k;
}
// 再次检查溢出
if (base_val > 1000000000000000000LL) {
base_val = 1000000000000000001LL;
}
}
// 计算首位在arr中的索引
ll idx0 = (pos - 1) / base_val;
cout << arr[idx0]; // 输出首位数字
// 处理剩余位数
if (r > 0) {
ll rem = (pos - 1) % base_val; // 剩余部分的位置
vector<int> digits(r, 0); // 存储各位数字索引
// 将rem转换为k进制表示
for (int i = 0; i < r; i++) {
digits[r - 1 - i] = rem % k; // 从低位到高位存储
rem /= k;
}
// 输出剩余位数的数字
for (int i = 0; i < r; i++) {
cout << d[digits[i]]; // 输出对应数字
}
}
cout << '\n'; // 换行
}
return 0;
}