嘘~ 正在从服务器偷取页面 . . .

洛谷P1748 H数 题解


洛谷P1748 H数 题解

题目链接:P1748 H数

题意

所谓 $H$ 数,是指只含有 $2,3,5,7$ 这些质因数的数,如 $630$ 是 $H$ 数,而 $22$ 不是。

现在要求输出第 $n$ 个 $H$ 数,即 $H_n$ (为了方便起见将 $H_1$ 定为 $1$ )。

已知 $n$ 不超过 $10000$,最后数据在 int64 范围之内。

输入格式

一行, $n$ 。

输出格式

一行,输出 $H_n$​ 。

虽说是 普及/提高− 的题,但是它的思路还是挺有意思的。

考虑dp,或者说考察 $H_n$ 的递推方式。

其中 $a,b,c,d$ 均满足特定形式,例如 $H_{a-1}\times 2 \le H_i < H_a \times 2$ 。

一种暴力的转移方式是,枚举 $j$ ,并钦定:例如当 $j$ 满足 $a$ 的条件时尝试用 $H_a$ 更新 $H_i$ 。

这样只需扫一遍 $[1,~i-1]$ 即可。注意到 $a,b,c,d$ 均随着 $i$ 的增长而不减。

因此我们可以直接维护四个指针 $a,b,c,d$ ,每次算出 $H_i$ 后,更新 $a,b,c,d$ 使他们重新满足条件。

时间复杂度 $\mathcal{O}(n)$

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
void up(int &x,int y) { x < y ? x = y : 0; }
void down(int &x,int y) { x > y ? x = y : 0; }
#define N ((int)(1e4 + 15))

int a,b,c,d,x[N];
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // freopen("check.in","r",stdin);
    // freopen("check.out","w",stdout);
    int n; cin >> n; x[1] = a = b = c = d = 1;
    for(int i = 2; i <= n; i++)
    {
        x[i] = x[a] * 2;
        if(x[i] > x[b] * 3) x[i] = x[b] * 3;
        if(x[i] > x[c] * 5) x[i] = x[c] * 5;
        if(x[i] > x[d] * 7) x[i] = x[d] * 7;
        if(x[i] == x[a] * 2) ++a;
        if(x[i] == x[b] * 3) ++b;
        if(x[i] == x[c] * 5) ++c;
        if(x[i] == x[d] * 7) ++d;
    }
    cout << x[n] << '\n';
    return 0;
}

参考文献

[1] https://www.luogu.com.cn/blog/user41920/solution-p1748


题外话

这和 H 有什么关系


文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录