Codeforces Round #701 (Div. 2) A~C 题解
写在前边
链接:Codeforces Round #701 (Div. 2)
数学场,题目描述简单粗暴,思路很妙,代码短的不行,都是好神奇的一些题目。
A. Add and Divide
链接:A题链接
题目大意:
给定两个正整数,我们可以进行两个操作:
最终目标是找到使变成的最小操作次数
思路:
因为每次只会变动,所以最开始思路就是,如果我们可以提前大体找到一个操作次数,我们在这个操作次数内进行枚举,而每次操作只会变动,所以假设一共有次操作,如果我们可以有次让加,然后变成了,然后让不断的除直到为,假设有次操作,那么答案就是次操作了,那么怎么才能找到这个呢,可以看数据范围,我们可以估计最差的情况,最差的情况就是当的时候,这时候我们首先要做的就是让,然后再让不断的除,直到为,而这最多需要次,所以!经过分析最差情况也就进行次操作左右,即所以我们只需要枚举到即可,最坏情况
代码:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <map>
#include <cstring>
using namespace std;
#define Inf 0x3f3f3f3f
#define PII pair<int, int>
#define P2LL pair<long long, long long>
#define endl '\n'
typedef long long LL;
typedef unsigned long long ULL;
typedef vector<long long> VLL;
typedef vector<int> VI;
void solve() {
int a, b, res = 35;
cin >> a >> b;
if (a < b) {
puts("1");
return;
}
for (int i = (b == 1 ? 1 : 0); i <= 30; i++) { //枚举多少次 最坏情况下就有30次
int tempa = a, tempres = i;
int tempb = b + i;
while (tempa) {
tempa /= tempb;
tempres++;
}
res = min(res, tempres);
}
cout << res << endl;
}
int main()
{
//ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int t;
scanf("%d", &t);
while (t--) {
solve();
}
system("pause");
return 0;
}
B. Replace and Keep Sorted
链接:B题链接
题目大意:
定义两个互为的数组:
- 都是严格单调递增
- 有相同的长度
- 它们的元素范围
- 它们只有一个数不同。
现在给定一个数组,并且给定一个区间,那么中的一个数组就是,长度为 那么另一个数组就是可以从中选个数,并且只与有一个数不同的数组,问有多少个这样的数组。
思路:
首先想到可以挨个枚举每一个位置可以选多少个数,那么最终答案就是每一个位置可以选的数之和,但是这样数据范围就是明显会超时,所以就想能不能在复杂度之内就能判断出一个区间中所有的可能,第个位置的数可以选个,第个位置的数可以选个,对于(注意是开区间!)能选多少个我们可以用前缀和处理,前缀和就是每一个区间可以选择的数的个数,时间复杂度就降为了.
代码:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <map>
#include <cstring>
using namespace std;
#define Inf 0x3f3f3f3f
#define PII pair<int, int>
#define P2LL pair<long long, long long>
#define endl '\n'
typedef long long LL;
typedef unsigned long long ULL;
typedef vector<long long> VLL;
typedef vector<int> VI;
const int N = 1e5 + 10;
int a[N], b[N];
void solve() {
int n, k, q;
scanf("%d%d%d", &n, &q, &k);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
a[n + 1] = k + 1;
for (int i = 1; i <= n; i++) {
b[i] += a[i + 1] - a[i - 1] - 2;
b[i] += b[i - 1];
}
while (q--) {
LL res = 0;
int l, r;
scanf("%d%d", &l, &r);
res += b[r - 1] - b[l]; //开区间
res += k - a[r - 1] - 1; //右边
res += a[l + 1] - 2; //左边
printf("%d\n", res);
}
}
int main()
{
//ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
solve();
return 0;
}
C. Floor and Mod
链接:C题链接
题目大意:
给定下下,现在要求求一个数对,使得, 要求, 。
思路:
首先暴力肯定不行,所以想能不能用直接求出来,那只要推公式了,让,所以推出,又因为,可以推出,所以,所以现在求出了的范围,现在要做的就是对于每一个固定的,如果我们可以推出或者数的范围,那么就可以求出数对可取的个数了,对于b,已知, ,根据 ,得出,因此得出的个数就是。
代码:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <map>
#include <cstring>
using namespace std;
#define Inf 0x3f3f3f3f
#define PII pair<int, int>
#define P2LL pair<long long, long long>
#define endl '\n'
typedef long long LL;
typedef unsigned long long ULL;
typedef vector<long long> VLL;
typedef vector<int> VI;
void solve() {
LL x, y;
cin >> x >> y;
LL res = 0;
for (LL k = 1; k * k <= x; k++) {
res += max(0LL, min(y, x / k - 1) - k);
}
cout << res << endl;
}
int main()
{
//ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int t;
scanf("%d", &t);
while (t--) {
solve();
}
system("pause");
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端