diff --git a/src/8/2/T644759.cpp b/src/8/2/T644759.cpp index d86f67f..d6cb827 100644 --- a/src/8/2/T644759.cpp +++ b/src/8/2/T644759.cpp @@ -1,38 +1,151 @@ -#include #include -#include -#include #include +using namespace std; -using ll = int64_t; -static inline constexpr std::string cvtfd(ll n,ll b){ - std::string s; - do{ - ll c=n%b; - s=char(c+'0')+s; - n/=b; - }while(n); - return s; -} -ll k,q; -std::vector d; -int main(){ - std::iostream::sync_with_stdio(false); - std::cin>>k; - d.resize(k); - for(char&c:d){ - ll tmp; - std::cin>>tmp; - c=tmp+'0'; +typedef long long ll; // 定义长整型别名,用于处理大数 + +int main() { + ios::sync_with_stdio(false); + cin.tie(0); // 优化输入输出速度 + + int k; + cin >> k; // 读取数字集合大小 + vector d(k); // 存储数字集合 + for (int i = 0; i < k; i++) { + cin >> d[i]; // 读取数字集合元素 } - std::cin>>q; - while(q--){ - ll n; - std::cin>>n; - std::string s = cvtfd(n,d.size()); - for(char c:s){ - std::cout< arr; + if (has_zero) { + // 如果含0,首位使用除0外的其他数字 + arr = vector(d.begin() + 1, d.end()); + } else { + // 如果不含0,所有数字都可用于首位 + arr = d; + } + + // 存储各长度幸运数的数量 + vector cnt; + // 存储幸运数数量的前缀和 + vector 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; } - std::cout<<'\n'; } -} \ No newline at end of file + + 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 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; +} diff --git a/src/8/2/T644760.cpp b/src/8/2/T644760.cpp new file mode 100644 index 0000000..bd4ca44 --- /dev/null +++ b/src/8/2/T644760.cpp @@ -0,0 +1,93 @@ +#include +#include +using namespace std; + +// 解决单次查询的函数,计算区间[l, r]内满足条件的(n, m)对数量 +long long solve(long long l, long long r) { + if (l > r) return 0; // 无效区间直接返回0 + + // 预处理l和r的31位二进制表示(从最高位到最低位) + int bits_r[31], bits_l[31]; // 存储二进制位 + for (int i = 0; i < 31; i++) { + // 提取r的第(30-i)位(最高位存储在bits_r[0]) + bits_r[i] = (r >> (30 - i)) & 1; + // 提取l的第(30-i)位(最高位存储在bits_l[0]) + bits_l[i] = (l >> (30 - i)) & 1; + } + + // DP数组:dp[i][tight_n][tight_l] + // i: 当前处理的位数(0-30) + // tight_n: n是否仍受r的上界约束(1-受约束,0-不受约束) + // tight_l: m是否仍受l的下界约束(1-受约束,0-不受约束) + long long dp[32][2][2]; + memset(dp, 0, sizeof(dp)); // 初始化DP数组为0 + dp[0][1][1] = 1; // 初始状态:从最高位开始,n和m都受约束 + + // 从高位到低位遍历31个二进制位 + for (int i = 0; i < 31; i++) { + // 遍历所有可能的约束状态 + for (int tight_n = 0; tight_n < 2; tight_n++) { + for (int tight_l = 0; tight_l < 2; tight_l++) { + if (dp[i][tight_n][tight_l] == 0) continue; // 跳过无效状态 + + // 确定n当前位的上限: + // 若受约束则上限为r的当前位,否则上限为1 + int up_n = (tight_n) ? bits_r[i] : 1; + + // 枚举n当前位的可能取值a(0或1) + for (int a = 0; a <= up_n; a++) { + // 根据m是否受下界约束分情况处理 + if (tight_l) { + // 若受约束,则m当前位b的下限为l的当前位 + int low_m = bits_l[i]; + // 枚举m当前位b的可能取值(从low_m到1) + for (int b = low_m; b <= 1; b++) { + // 检查子集条件:m的位不能超过n + if (b == 1 && a == 0) continue; // 违反条件则跳过 + + // 计算新的约束状态: + // 若之前受约束且当前位等于边界值,则继续保持约束 + int new_tight_n = tight_n && (a == bits_r[i]); + int new_tight_l = tight_l && (b == bits_l[i]); + + // 状态转移:累加方案数 + dp[i+1][new_tight_n][new_tight_l] += dp[i][tight_n][tight_l]; + } + } else { + // 若不受约束,则b可取0或1 + for (int b = 0; b <= 1; b++) { + // 检查子集条件 + if (b == 1 && a == 0) continue; + + // 计算新的约束状态(下界约束保持解除状态) + int new_tight_n = tight_n && (a == bits_r[i]); + int new_tight_l = tight_l; // 下界约束一旦解除不再恢复 + dp[i+1][new_tight_n][new_tight_l] += dp[i][tight_n][tight_l]; + } + } + } + } + } + } + + // 统计所有最终状态的结果 + long long ans = 0; + for (int i = 0; i < 2; i++) + for (int j = 0; j < 2; j++) + ans += dp[31][i][j]; + return ans; +} + +int main() { + ios::sync_with_stdio(false); + cin.tie(0); // 优化输入输出 + + int q; + cin >> q; // 读取查询次数 + while (q--) { + long long l, r; + cin >> l >> r; // 读取查询区间 + cout << solve(l, r) << '\n'; // 输出答案 + } + return 0; +} diff --git a/src/8/2/T644761.cpp b/src/8/2/T644761.cpp new file mode 100644 index 0000000..6e9a308 --- /dev/null +++ b/src/8/2/T644761.cpp @@ -0,0 +1,52 @@ +#include +#include +#include +using namespace std; + +typedef long long ll; +const int MOD = 998244353; + +int main() { + iostream::sync_with_stdio(false); + cin.tie(nullptr); + ll n, a, b, c; + cin >> n >> a >> b >> c; + + + vector> C(n+1, vector(n+1, 0)); + for (int i = 0; i <= n; i++) { + C[i][0] = 1; + for (int j = 1; j <= i; j++) { + C[i][j] = (C[i-1][j-1] + C[i-1][j]) % MOD; + } + } + + + auto S = [&](ll m, ll x) -> ll { + if (m < 0) return 0; + ll up = min(m, x); + ll sum = 0; + for (int i = 0; i <= up; i++) { + sum = (sum + C[m][i]) % MOD; + } + return sum; + }; + + + ll ans = 0; + for (int k = 0; k <= n; k++) { + ll m = n - k; + ll t = C[n][k]; + t = t * S(m, a) % MOD; + t = t * S(m, b) % MOD; + t = t * S(m, c) % MOD; + + if (k % 2 == 1) { + t = MOD - t; + } + ans = (ans + t) % MOD; + } + + cout << (ans % MOD + MOD) % MOD << endl; + return 0; +}