欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 建筑 > 【CF】Day74——⭐Codeforces Round 885 (Div. 2) ACD (数学场)

【CF】Day74——⭐Codeforces Round 885 (Div. 2) ACD (数学场)

2025/6/6 7:06:54 来源:https://blog.csdn.net/qq_61422664/article/details/148405099  浏览:    关键词:【CF】Day74——⭐Codeforces Round 885 (Div. 2) ACD (数学场)

A. Vika and Her Friends

题目:

思路:

经典博弈题,考虑奇偶性

我们来看看简单版,即只有一个追逐者的情况

我们可以将网格划分成一个国际象棋的棋盘,然后再来观察题目

如果二者处于相同的颜色格子中,那么就一定能追到,否则一定不行,具体的来说,如果二者的距离是偶数,那么就一定能追到,否则一定不行

证明:我们观察每次移动会发生什么,由于每次必须移动,那么二者的距离就可能会发生改变,有三种情况,即距离不变,距离 -2,距离 +2,所以我们能发现一个规律,即每次移动二者距离差是一个偶数,由于距离差不能是负数,即 dis >= 0 恒成立,而 dis = 0 时说明相交了,所以我们得考虑 dis 的奇偶性,由于每次都是改变偶数,那么只有当 dis 初始值是偶数时我们才能减少到 0,否则如果是奇数,那么我们最多只能减少到 1

回到本题,由于其中的棋子能处于同一个位置,那么每个棋子的决策是互不影响的,所以我们只需要找到是否存在一个棋子满足 dis % 2 = 0 即可

代码:

#include <iostream>
#include <algorithm>
#include<cstring>
#include<cctype>
#include<string>
#include <set>
#include <vector>
#include <cmath>
#include <queue>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <stack>
#include <memory>
using namespace std;
#define int long long
#define yes cout << "Yes\n"
#define no cout << "No\n"void solve()
{int n, m, k;cin >> n >> m >> k;int x, y;cin >> x >> y;vector<pair<int, int>> pos(k);int flag = 0;for (int i = 0; i < k; i++){cin >> pos[i].first >> pos[i].second;if ((pos[i].first + pos[i].second) % 2 == (x+y) % 2){flag = 1;}}if (flag){no;return;}yes;
}signed main()
{cin.tie(0)->sync_with_stdio(false);int t = 1;cin >> t;while (t--){solve();}return 0;
}

C. Vika and Price Tags

题目:

思路:

找规律,考虑模与循环

那我们来分析题意,看到数据这么大,如果直接死算的话肯定不行,所以考虑找规律

由于对于每一个 a b 都是一个独立的操作,所以接下来我们单独分析

若 a = 0,,b = 0,那么无论怎么操作都是 0 0

若 a = 0, b !=0,假设我们要执行操作,那么就有 0 b -> b b -> b 0 -> 0 b,到此我们发现又回到了 0 b,此时我们一共操作了 3 次,也就是说如果到了 a = 0,b != 0 这种形式时,只要后面执行的次数是 3 的倍数那么就不会变化

总体上将,假设 i 的操作数是 cnt[i],那么就要满足以下式子:

cnt[0] % 3 = cnt[1] % 3 = cnt[2] % 3 = ... = cnt[n] % 3

那么如何计算cnt呢?我们如果暴力枚举的话肯定不行,所以考虑其中的规律or结论来优化

我们现在只考虑始终 a > b 的情况,考虑枚举看看是否有规律

(a, b) -> (b, a - b) -> (a - b, a - 2*b) -> (a - 2*b, b),到这里我们可以发现,b还是那个b,但是 a 减去了 2*b,且只进行了三次操作(这和上面的 mod 3 刚好对上了一点联系,太妙了)

所以我们只需要 a >= 2*b,那我们就可以执行 k*3 次操作后变成 (a % 2b, b) 形式,此时 a < 2*b,也就是说我们纯模拟一次就行

那我们就可以开始写了,具体的实现看代码

代码:

#include <iostream>
#include <algorithm>
#include<cstring>
#include<cctype>
#include<string>
#include <set>
#include <vector>
#include <cmath>
#include <queue>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <stack>
#include <memory>
using namespace std;
#define int long long
#define yes cout << "Yes\n"
#define no cout << "No\n"void solve()
{int n;cin >> n;vector<int> a(n), b(n);for (int i = 0; i < n; i++){cin >> a[i];}for (int i = 0; i < n; i++){cin >> b[i];}set<int> has;for (int i = 0; i < n; i++){if (a[i] == b[i] && a[i] == 0){continue;}int cnt = 0;while (a[i]){b[i] %= 2 * a[i];int temp = abs(a[i] - b[i]);a[i] = b[i];b[i] = temp;cnt++;cnt %= 3;}has.insert(cnt);}if (has.size() <= 1){yes;return;}no;
}signed main()
{cin.tie(0)->sync_with_stdio(false);int t = 1;cin >> t;while (t--){solve();}return 0;
}

D. Vika and Bonuses

题目:

思路:

数学,想到了二次函数,但没考虑不同的个位的答案可能更优

我们先来处理一下特殊情况,即操作二没意义的情况,此时 x 的最后一位是 0,那么什么时候最后一位会是 0 呢,即 x % 10 == 0 时或 x % 10 == 5 时,为什么 x % 10 == 5 也要算呢?因为我们执行了一次这个操作后就会变成 0,所以我们也要考虑 5,此时我们特判即可

那看其他情况,我们来看看每一个数执行操作二会变成什么?

1->2 2->4 3->6 4->8 6-> 2 7->4 8->6 9->8

我们发现偶数会形成一个循环,即 2 4 6 8,而其他奇数只需要多一步就能进入这个循环,所以我们可以来考虑一般情况

假设现在是 s,如果我们选择走过了 x 个循环,那么最后的价值就是

val = (s + 20x)(k -4x)

展开可得

val = -80x^{2} + (20k - 4s)x+sk

可以看到这时一个二次函数,那么对于二次函数的最大值,我们可以考虑三分或者套公式(不会三分,这里直接套公式)

小学就知道的公式,二次函数极值的x坐标公式为 x =-b/2a,这里就是 (5k - s) / 40,所以我们令 x 等于这个坐标即可

但是由于这个坐标可能不是整数,所以我们要检查向上取整和向下取整两种可能取最大值

还有情况就是我们可以不循环,以及 s 可以不走循环,以此枚举取最大值即可

代码:

#include <iostream>
#include <algorithm>
#include<cstring>
#include<cctype>
#include<string>
#include <set>
#include <vector>
#include <cmath>
#include <queue>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <stack>
#include <memory>
using namespace std;
#define int long long
#define yes cout << "Yes\n"
#define no cout << "No\n"int fuc(int s,int k,int x)
{return (s + 20 * x) * (k - 4 * x);
}
int xianzhi(int x,int k)
{return max(0LL, min(x, k / 4));
}
int getmx(int s,int k)
{int ans = s * k;int x1 = (5 * k - s) / 40;x1 = xianzhi(x1, k);int x2 = (5 * k - s + 39) / 40;x2 = xianzhi(x2, k);return max({ ans,fuc(s,k,x1),fuc(s,k,x2) });
}void solve()
{int s, k;cin >> s >> k;if (s % 10 == 0){cout << s * k << endl;}else if(s % 10 == 5){cout << max(s * k,(s+5) * (k-1)) << endl;}else{int ans = s * k;if (s % 2){s += s % 10;k--;}//多走几次看看for (int i = 1;k && i <= 4; i++){ans = max(ans, getmx(s, k));s += s % 10;k--;}cout << ans << endl;}
}signed main()
{cin.tie(0)->sync_with_stdio(false);int t = 1;cin >> t;while (t--){solve();}return 0;
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com