Codeforces Round 1006 (Div. 3)
A. cntew World, cntew Me, cntew Array
题目大意
给你一个长为n的全0数组,每个位置可以修改为不超过p的绝对值的数字,要求和为k,求最小操作次数,不可能输出-1
解题思路
显然前面尽可能的拉满,然后看最后需不需要额外补一个就行
代码实现
#include <bits/stdc++.h>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int tt;
std::cin >> tt;
while (tt--) {
int n, k, p;
std::cin >> n >> k >> p;
k = std::abs(k);
if (n * p < k) {
std::cout << -1 << "\n";
} else {
std::cout << (k + p - 1) / p << "\n";
}
}
}
B. Having Been a Treasurer in the Past, I Help Goblins Deceive
题目大意
给你一个字符串只包含 "-" 和 "_",让你重排字符串,问最多能有多少子序列是 "-_-"
解题思路
显然把"_"放中间,"-"平均放两边是最多的
代码实现
#include <bits/stdc++.h>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int tt;
std::cin >> tt;
while (tt--) {
i64 n, cnt = 0;
std::cin >> n;
std::string s;
std::cin >> s;
for (auto ch : s) {
cnt += ch == '_';
}
std::cout << cnt * ((n - cnt) / 2 * ((n - cnt + 1) / 2)) << "\n";
}
}
C. Creating Keys for StOansrages Has Become My Main Skill
题目大意
给定n和x,要求用不超过n个数字使得它们按位或等于x,同时要让这些数字的mex尽可能大
解题思路
枚举mex,如果当前mex不会让x产生变化则一直枚举下去
代码实现
#include <bits/stdc++.h>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int tt;
std::cin >> tt;
while (tt--) {
int n, x, mex = 0, cnt = 0;
std::cin >> n >> x;
while (mex < n && ((mex & x) == mex)) {
cnt |= mex;
mex++;
}
if (mex == n && cnt != x) {
mex--;
}
for (int i = 0; i < n; i++) {
std::cout << (i < mex ? i : x) << " \n"[i == n - 1];
}
}
}
D. For Wizards, the Exam Is Easy, but I Couldn't Handle It
题目大意
允许操作一次,把位于l的数字放到r,求让逆序对最少的任意一组lr
解题思路
n的范围很小,因此暴力枚举每一个i换到右边的每一个位置的时候,让顺序逆序倒置的数量差求个最大值即可
代码实现
#include <bits/stdc++.h>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int tt;
std::cin >> tt;
while (tt--) {
int n;
std::cin >> n;
std::vector<int> a(n);
for (int i = 0; i < n; i++) {
std::cin >> a[i];
}
int l = 0, r = 0, cnt = 0;
for (int i = 0; i < n; i++) {
int cnt1 = 0, cnt2 = 0;
for (int j = i + 1; j < n; j++) {
cnt1 += a[i] > a[j];
cnt2 += a[i] < a[j];
if (cnt < cnt1 - cnt2) {
l = i, r = j;
cnt = cnt1 - cnt2;
}
}
}
std::cout << l + 1 << " " << r + 1 << "\n";
}
}
E. Do You Love Your Hero and His Two-Hit Multi-Target Attacks?
题目大意
构造不超过五百个点对,使他们之间欧氏距离等于曼哈顿距离的点对数量为k
解题思路
首先计算全在一条线上的数量,发现远超最大的要求,而最小值显然就是0,因此考虑会有多条平行线段,发现他们对目标值的贡献大小是可控的,所以答案就在其中,每次新开一条不重叠的线段一直算贡献直到小于k的最大,重复直到k为0即可
代码实现
#include <bits/stdc++.h>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int tt;
std::cin >> tt;
while (tt--) {
int k, x = 0, y = 0, cnt = 0;
std::cin >> k;
std::vector<std::array<int, 2>> ans;
while (cnt < k) {
std::vector<std::array<int, 2>> xy;
for (int i = 0; y < k; i++) {
if (cnt + i > k) {
break;
}
xy.push_back({x, y});
ans.push_back({x, y});
cnt += i;
x++;
}
y++;
}
std::cout << ans.size() << "\n";
for (auto [x, y] : ans) {
std::cout << x << " " << y << "\n";
}
}
}
F. Goodbye, Banker Life
题目大意
类似杨辉三角,其中把加法换成异或,输出第n行
解题思路
显然输出的元素不是0就是k,打表发现组合数为偶数的输出0,奇数的输出k,于是可以转换为对组合数%2(此处的组合数是
代码实现
// 做法1
#include <bits/stdc++.h>
using i64 = long long;
i64 ksm(i64 a, i64 n, i64 mod) {
i64 res = 1;
a = (a % mod + mod) % mod;
while (n) {
if (n & 1) {
res = (a * res) % mod;
}
a = (a * a) % mod;
n >>= 1;
}
return res;
}
int C(int n, int m, int mod) {
if (m > n) {
return 0;
}
int res = 1;
for (int i = 1, j = n; i <= m; i++, j--) {
res = (i64)res * j % mod;
res = (i64)res * ksm(i, mod - 2, mod) % mod;
}
return res;
}
int lucas(i64 a, i64 b, i64 p) {
if (a < p && b < p) {
return C(a, b, p);
}
return (i64)C(a % p, b % p, p) * lucas(a / p, b / p, p) % p;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int tt;
std::cin >> tt;
while (tt--) {
int n, k;
std::cin >> n >> k;
for (int i = 0; i < n; i++) {
std::cout << lucas(n - 1, i, 2) * k << " \n"[i == n - 1];
}
}
}
// 做法2
#include <bits/stdc++.h>
using i64 = long long;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int tt;
std::cin >> tt;
while (tt--) {
int n, k;
std::cin >> n >> k;
for (int i = 0; i < n; i++) {
std::cout << ((n - 1 & i) == i) * k << " \n"[i == n - 1];
}
}
}
G. I've Been Flipping Numbers for 300 Years and Calculated the Sum
题目大意
给你n,k,求2-k进制下的n反转后变回十进制的和,对答案模1e9+7
解题思路
可以发现k>n的部分只有一位,
- k > n
- 2 -
-
对于这个两位数(
设
代码实现
#include <bits/stdc++.h>
using i64 = long long;
const int MOD = 1e9 + 7;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int tt;
std::cin >> tt;
while (tt--) {
i64 n, k, ans = 0;
std::cin >> n >> k;
if (k > n) {
ans = ans + (k - n) % MOD * n % MOD;
k = n;
}
for (int i = 2; i <= std::min((i64)std::sqrt(n), k); i++) {
i64 x = n, res = 0;
while (x) {
res = (res * i + x % i) % MOD;
x /= i;
}
ans = (ans + res) % MOD;
}
auto sum1 = [&](i64 l, i64 r) -> i64 { return (r * (r + 1) / 2 - l * (l + 1) / 2) % MOD; };
auto sum2 = [&](i64 l, i64 r) -> i64 { return (r * (r + 1) * (2 * r + 1) / 6 - l * (l + 1) * (2 * l + 1) / 6) % MOD; };
for (int l = sqrt(n) + 1, r; l <= k; l = r + 1) {
r = std::min(n / (n / l), k);
i64 a = n % l, d = n / l;
ans += (r - l + 1) * d % MOD;
ans += sum1(l - 1, r) * n % MOD;
ans -= sum2(l - 1, r) * d % MOD;
}
std::cout << (ans % MOD + MOD) % MOD << "\n";
}
}
分类:
Codeforces
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架