当前位置: 首页 > news >正文

【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;
}

相关文章:

  • 2025.6.3学习日记 Nginx 基本概念 配置 指令 文件
  • Nginx配置Ollama 访问api服务
  • 61、ESB详解
  • RTP over TCP 模式
  • Ros2 简单构建项目的流程以及涉及的文件作用
  • 【iOS安全】Macbook更换brew源
  • AI一周事件(2025年5月27日-6月2日)
  • 在图像分析算法部署中应对流行趋势的变化|文献速递-深度学习医疗AI最新文献
  • 【北邮 操作系统】第十二章 文件系统实现
  • Windows应用-音视频捕获
  • MongoTemplate常用api学习
  • 四元素、旋转矩阵与旋转向量
  • 小体积涵盖日常办公等多功能的软件
  • 第三章 3.MAC Address(CCNA)
  • linux的实时性
  • C++学者给您讲数学之——数列
  • Spring 中如何开启事务?
  • 黑马程序员TypeScript课程笔记—class篇
  • 软件工程的定义与发展历程
  • 如何避免工具过多导致的效率下降
  • 网站建设进度表 免费下载/网站建设合同模板
  • 有什么做视频的免费素材网站/sem推广什么意思
  • 天天seo伪原创工具/百度关键词优化排名技巧
  • 做百度手机网站优化点/湖南有实力seo优化哪家好
  • 手机论坛网站/学企业管理培训班
  • 导航网站网站提交怎么做/网络营销和传统营销的区别