A.B - Savings
大致思路为求1到n的和,如果结果大于等于k救输出当前值
#include <iostream>
#include <algorithm>
using namespace std;
constexpr int N = 2010, M = 1010;
typedef long long ll;
char a[N][M];
void solve() {
ll n;
cin >> n;
ll sum = 0;
ll count = 0;
for (ll i = 1; i <= n; i++) {
sum += i; // 计算当前的和
if (sum >= n) { // 如果和大于等于n
cout << count + 1 << "\n"; // 输出结果(count加1)
break; // 跳出循环
} else {
count++; // 否则,增加count的值
}
}
}
int main() {
int t;
//cin >> t;
t = 1;
while (t--) {
solve(); // 调用solve函数
}
}
B.C - abc285_brutmhyhiizp
该题可以转化为26进制转化为十进制
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
constexpr int N = 2010, M = 1010;
typedef long long ll;
// 解决问题的函数
void solve() {
string s;
cin >> s;
ll sum = 0;
int n = s.size();
for (int i = 0; i < s.size(); i++) {
ll p = pow(26, n - i - 1); // 计算 26 的 n - i - 1 次幂
sum += (s[i] - 'A' + 1) * p; // 将字符转换为对应的数值并乘以权值 p,然后累加到 sum
}
cout << sum << "\n"; // 输出结果
}
int main() {
int t;
//cin >> t; // 输入测试用例数量
t = 1; // 假设只有一个测试用例
while (t--) {
solve(); // 调用解决问题的函数
}
}
c.B - K-th Common Divisor
这道题目数据很小,可直接暴力从1跑到A与B的最小值
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
constexpr int N = 2010, M = 1010;
typedef long long ll;
// 解决问题的函数
void solve() {
int a, b, k;
cin >> a >> b >> k; // 输入 a、b 和 k 的值
int n = min(a, b); // 取 a 和 b 中的较小值作为循环的上界
int count = 0; // 计数器,记录满足条件的个数
for (int i = n; i >= 1; i--) {
if (a % i == 0 && b % i == 0) { // 如果 i 是 a 和 b 的公约数
count++; // 计数器加一
}
if (count == k) { // 如果计数器达到 k
cout << i << "\n"; // 输出当前的公约数并结束函数
return ;
}
}
}
int main() {
int t;
//cin >> t; // 输入测试用例数量
t = 1; // 假设只有一个测试用例
while (t--) {
solve(); // 调用解决问题的函数
}
}
D.C - Colorful Candies
该题是一道滑动窗口的题目,每一次的数量变化都与最后的那个值有关,可以借助哈希表来存储每一次滑动糖果颜色数量的值
#include <iostream>
#include <algorithm>
#include <cmath>
#include <map>
using namespace std;
constexpr int N = 3e5 + 10, M = 1010;
typedef long long ll;
int c[N];
map<int,int> mp, mp1;
// 解决问题的函数
void solve() {
int n, k;
cin >> n >> k; // 输入 n 和 k 的值
int count = 0; // 计数器,记录不同元素的个数
for (int i = 1; i <= n; i++) {
cin >> c[i]; // 输入数组元素
if (mp[c[i]] == 0) { // 如果当前元素还没有出现过
count++; // 计数器加一
mp[c[i]]++; // 标记当前元素已经出现过
}
}
if (k == n) { // 如果 k 等于数组长度
cout << count << "\n"; // 输出不同元素的个数并结束函数
return ;
}
if (count == 1) { // 如果数组中只有一个不同的元素
cout << 1 << "\n"; // 输出 1 并结束函数
return ;
}
int sum = 0; // 记录最大不同元素个数
for (int i = 1; i <= n; i++) {
mp1[c[i]]++; // 将当前元素加入到临时计数器中
if (i > k) { // 如果当前位置大于 k
mp1[c[i - k]]--; // 从临时计数器中减去之前的元素
if (mp1[c[i - k]] == 0) { // 如果之前的元素已经没有了
mp1.erase(c[i - k]); // 从临时计数器中删除该元素
}
}
int s = mp1.size(); // 统计临时计数器中不同元素的个数
sum = max(s, sum); // 更新最大不同元素个数
}
cout << sum << "\n"; // 输出最大不同元素个数
}
int main() {
int t;
//cin >> t; // 输入测试用例数量
t = 1; // 假设只有一个测试用例
while (t--) {
solve(); // 调用解决问题的函数
}
}
E.D - Triangles
这个题目的数据有点水,直接暴力开三次方也可以过。他的正解则是找到其中两条边,第三条边可以通过二分来找到。
手写lower_bound:
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
constexpr int N = 2e3 + 10, M = 1010;
typedef long long ll;
int n;
int a[N];
// 在区间 [l, r] 内寻找第一个大于等于 x 的元素的下标
int check(int l, int r, int x) {
while(l <= r) {
int mid = l + r >> 1; // 计算中间位置的索引
if(a[mid] < x) {
l = mid + 1; // 如果中间元素小于 x,更新左边界
}
else {
r = mid - 1; // 否则更新右边界
}
}
return l; // 返回第一个大于等于 x 的元素的下标
}
void solve() {
cin >> n; // 输入数组长度
for (int i = 1; i <= n; i++) {
cin >> a[i]; // 输入数组元素
}
sort(a + 1, a + n + 1); // 对数组进行升序排序
ll count = 0; // 计数器,记录满足条件的对数
for(int i = 1; i <= n; i++) {
for(int j = i + 1; j <= n; j++) {
int p = check(1, n, a[i] + a[j]); // 找到满足 a[i] + a[j] 的第一个元素的下标
count += p - j - 1; // 更新计数器
}
}
cout << count << "\n"; // 输出满足条件的对数
}
int main() {
int t;
t = 1; // 假设只有一个测试用例
//cin >> t; // 输入测试用例数量
while (t--) {
solve(); // 调用解决问题的函数
}
return 0;
}
直接用lower_band:
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
int N = 3e5 + 10, M = 1010;
typedef long long ll;
int n;
vector<int> v;
// 解决问题的函数
void solve() {
cin >> n; // 输入元素数量
for (int i = 1; i <= n; i++) {
int a;
cin >> a; // 输入每个元素的值
v.push_back(a); // 将元素加入 vector 容器
}
sort(v.begin(), v.end()); // 对 vector 容器中的元素进行升序排序
ll count = 0; // 计数器,记录满足条件的对数
for (int i = 0; i < n - 2; i++) {
for (int j = i + 1; j < n - 1; j++) {
// 使用二分搜索找到大于等于 v[i] + v[j] 的第一个元素
auto it = lower_bound(v.begin(), v.end(), v[i] + v[j]);
ll d = distance(it, v.end()); // 计算满足条件的元素个数
count += (n - 1 - j) - d; // 更新计数器
}
}
cout << count << "\n"; // 输出满足条件的对数
}
int main() {
int t;
t = 1; // 假设只有一个测试用例
//cin >> t; // 输入测试用例数量
while (t--) {
solve(); // 调用解决问题的函数
}
return 0;
}
F.C - Reorder Cards
该题使用的方法就是离散化加排序,对每一行,每一列进行排序。
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
constexpr int N = 3e5 + 10, M = 1010;
struct number{
int a;
int b;
int v1;
int v2;
int id;
}nu[N];
bool cmp(struct number x, struct number y) {
return x.a < y.a;
}
bool cmp1(struct number x, struct number y) {
return x.b < y.b;
}
bool cmp2(struct number x, struct number y) {
return x.id < y.id;
}
void solve() {
int h, w, n;
cin >> h >> w >> n; // 输入矩阵的高度、宽度以及元素数量
for (int i = 0; i < n; i++) {
cin >> nu[i].a >> nu[i].b; // 输入每个元素的 a 值和 b 值
nu[i].id = i + 1;
}
sort(nu, nu + n, cmp); // 根据 a 值对 nu 数组进行升序排序
nu[0].v1 = 1;
for (int i = 1; i < n; i++) {
if (nu[i].a == nu[i - 1].a) {
nu[i].v1 = nu[i - 1].v1; // 如果当前元素的 a 值与前一个元素的 a 值相等,则 v1 值也相等
} else {
nu[i].v1 = nu[i - 1].v1 + 1; // 否则,v1 值加一
}
}
sort(nu, nu + n, cmp1); // 根据 b 值对 nu 数组进行升序排序
nu[0].v2 = 1;
for (int i = 1; i < n; i++) {
if (nu[i].b == nu[i - 1].b) {
nu[i].v2 = nu[i - 1].v2; // 如果当前元素的 b 值与前一个元素的 b 值相等,则 v2 值也相等
} else {
nu[i].v2 = nu[i - 1].v2 + 1; // 否则,v2 值加一
}
}
sort(nu, nu + n, cmp2); // 根据 id 值对 nu 数组进行升序排序
for (int i = 0; i < n; i++) {
cout << nu[i].v1 << " " << nu[i].v2 << "\n"; // 输出每个元素的 v1 值和 v2 值
}
}
int main() {
int t;
t = 1; // 设置 t 的值为 1
while (t--) {
solve();
}
}