2025.7.17(补)
刷题日记
傻逼
Codeforces Round 1037 (Div. 3) D. This Is the Last Time
https://codeforces.com/contest/2126/problem/D
给定n个“赌场”,每个赌场有三个属性:l,r,real
如果当前钱币数在l和r之间,则可通过这个赌场将当前钱币数变为real
可以不必选择所有的赌场,顺序也可以任选,求可能获得的最大钱币数
如果没有限制的话,这道题就不能用贪心的思路了,需要考虑搜索或DP
但是这道题题目限制real一定在l和r之间,所以只需要结构体排序一下即可
我他妈真是个傻逼
点击查看代码
void solve () {
int n, k;
std::cin >> n >> k;
typedef struct node {
int l, r, real;
} node;
std::vector<node> a(n + 1);
for (int i = 1; i <= n; i++) {
std::cin >> a[i].l >> a[i].r >> a[i].real;
}
std::sort(a.begin() + 1, a.end(), [&] (node a, node b) {
if (a.real != b.real) return a.real < b.real;
if (a.l != b.l) return a.l < b.l;
return a.r > b.r;
});
for (int i = 1; i <= n; i++) {
if (a[i].l <= k && k <= a[i].r) {
k = std::max(a[i].real, k);
}
}
std::cout << k << '\n';
}
再给个广搜写法的代码,会超时,但是如果这道题real无限制,那么可能就是这种思路
点击查看代码
void solve () {
int n, k;
std::cin >> n >> k;
typedef struct node {
int l, r, real;
} node;
std::vector<node> a(n + 1);
for (int i = 1; i <= n; i++) {
std::cin >> a[i].l >> a[i].r >> a[i].real;
}
std::queue<int> q;
std::vector<int> vis(n + 1, 0);
q.push(k);
int ans = k;
while (q.size()) {
auto now = q.front();
ans = std::max(ans, now);
q.pop();
for (int i = 1; i <= n; i++) {
if (!vis[i] && a[i].l <= now && now <= a[i].r) {
q.push(a[i].real);
vis[i] = 1;
}
}
}
std::cout << ans << '\n';
}
Codeforces Round 1037 (Div. 3) E. G-C-D, Unlucky!
给定两个数组p和s,分别为某数组的前缀GCD数组和后缀GCD数组,请判断是否合法
这道题的思路特别简单,首先我们知道
前缀GCD数组p[i] = std::__gcd(p[i - 1], a[i]);
后缀GCD数组s[i] = std::__gcd(s[i + 1], a[i]);
那么我们可以知道,a[i] % p[i] == 0 && a[i] % s[i] == 0 一定成立
因此我们可以令a[i] = LCM(p[i], s[i]),也是满足条件的
我们构造出了数组a之后,再去求数组a的前后缀GCD数组,和题中给的数组比较
如果一模一样就输出YES,反之NO,代码如下
点击查看代码
void solve () {
int n;
std::cin >> n;
std::vector<i64> pre(n + 1), suf(n + 1);
std::vector<i64> a(n + 1), p(n + 1), s(n + 1);
for (int i = 1; i <= n; i++) {
std::cin >> pre[i];
}
for (int i = 1; i <= n; i++) {
std::cin >> suf[i];
}
for (int i = 1; i <= n; i++) {
a[i] = pre[i] * suf[i] / std::__gcd(pre[i], suf[i]);
}
p[1] = a[1], s[n] = a[n];
for (int i = 2; i <= n; i++) {
p[i] = std::__gcd(p[i - 1], a[i]);
}
for (int i = n - 1; i >= 1; i--) {
s[i] = std::__gcd(s[i + 1], a[i]);
}
for (int i = 1; i <= n; i++) {
if (p[i] != pre[i] || s[i] != suf[i]) {
std::cout << "NO\n";
return;
}
}
std::cout << "YES\n";
}
Codeforces Round 1011 (Div. 2) C. Serval and The Formula
https://codeforces.com/problemset/problem/2085/C
给定两个正整数x,y,请找到一个k ∈ [0, 1e18],使得 (x + k) + (y + k) == (x + k) ^ (y + k)
我们设a = x + k, b = y + k,为了使得a + b == a ^ b,需要满足什么呢?
我们用二进制来表示,对于10101 和 01010,我们可以发现他们满足这个等式
也就是说,对于a和b两个数,如果他们任何一个二进制位都没有同时为1,那么就满足a + b == a ^ b!
换句话说,a + b == a ^ b 等价于 a & b == 0!
又因为2的幂的二进制表示总是1000000000这样的,并且2的幂,与任何小于它的正整数都没有公共位
所以我们的目的是,让x或者y,其中一个+k之后变成2的幂次,代码如下
点击查看代码
void solve () {
/*
对于 a + b == a ^ b
说明 对于a和b上任何一个二进制位,都没有同时为1的情况
也就是说 a & b == 0
因为2的幂的二进制表示总是1000000000这样的
并且2的幂,与任何小于它的正整数都没有公共位
所以我们的目的是,让x或者y,其中一个+k之后变成2的幂次
*/
i64 x, y;
std::cin >> x >> y;
if (x == y) {
std::cout << "-1\n";
return;
}
std::cout << (1LL << 48) - std::max(x, y) << '\n';
}