(2024年2月洛谷大更新,取消了个人博客功能,将博客转为推文,遂决定自行搭建Blog,并将文章迁移至此 (其实就只有两篇2333) )
其实在很久之前就想搞一个自己的blog了,每次浏览大佬的blog都会被大佬们自己搭建的世界所触动,现如今 $Messywind$ 学长给我们的每人创建一个blog养成写发电小作文的建议也算是促成这个blog的契机。
顺便进行第一篇题解的写:
啥都不会的人写的题解真的可以看嘛2333
题目 受害者 来自于AtCoder Beginner Contest 336 的 $C$ 题。C - Even Digits
题目大意是:当一个数的各位都是偶数时,称作这个数为好数 $(good\ integer)$,需要我们求第 $N$ 小的 $good\ integer$ 。
当看到这道题的时候,第一个想法是暴力枚举,声明一个 $count$ 变量,从 $0$ 开始枚举,如果符合条件则 $count$++,当 $count==N$ 时,则是所求的答案。
但是当我看了一眼数据范围……
$1≤N≤10^{12}$
$1≤N≤10^{12}$
$1≤N≤10^{12}$
emmm……虽然时间限制给到了 $2s$ ,但是还是会超时,所以选择更优的算法比较好。
首先让我们先枚举一下题干所定义的 $good\ integer$ :
$0\ 2\ 4\ 6\ 8$
$20\ 22\ 24\ 26\ 28$
$40\ 42\ 44\ 46\ 48$
$60\ ………$
$80\ ………$
$200\ ………$
$220\ …………$
其实规律就已经很明显了,我们可以发现这些数字每 $5$ 个进位一次,也就是说,这些 $good integer$ 本质上是一组步长为 $2$ 的五进制数,那么很显而易见地,我们可以将 $N$ 转化为五进制数,输出转化后的第 $N$ 个数即为我们所需要求的答案。
需要注意的是,因为第一个数是 $0$ ,所以我们实际求得结果时要将 $N$ 减去一再乘步长即 $answer = (N-1)×2$ ,此时的 $N$ 是转化为五进制数之后的。
因为牵扯到进位转换操作,所以转化为五进制之后的 $N$ 在做减法时并不能直接减一,所以要使用类似于高精度减法的思想来将其放在数组中进行操作。即:
if (!vec[0])
{
int brw = 1;
for (int i = 0; i < len; i++)
{
vec[i] -= brw;
brw = 0;
if (vec[i] < 0)
{
vec[i] += 5;
brw = 1;
}
}
}只有当个位数字为 $0$ 时我们才需要退位操作,所以在操作之前需要判断一下个位是否为 $0$ 来判断是否有必要进行退位。
随后逆序输出即为答案。
完整 $AC$ 代码如下:
#define _CRT_SECURE_NO_WARNINGS
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<queue>
#include<stack>
#include<string>
using namespace std;
#define int long long
#define endl '\n'
int n, m, a, t, b, k, y, h;
const int MAXN = 1e6 + 10;
const int MOD = 998244353;
int arr[MAXN];
signed main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n;
vector<int>vec;
while (n)
{
vec.push_back(n % 5);
n /= 5;
}
int len = vec.size();
if (!vec[0])
{
int brw = 1;
for (int i = 0; i < len; i++)
{
vec[i] -= brw;
brw = 0;
if (vec[i] < 0)
{
vec[i] += 5;
brw = 1;
}
}
}
else
vec[0]--;
for (int i = len - 1; i >= 0; i--)
cout << vec[i]*2;
}
有人提交时忘记删除测试用的输出代码导致WA了一发我不说是谁(悲
大胆提交,压力留给队友.jpg
至此,蒟蒻的第一篇blog&&第一篇题解就结束啦!