题解 | #智乃的数字#
智乃的数字
https://www.nowcoder.com/practice/8f1b8129db30467787167da1a589b324
这是一个非常经典的数论找规律问题。既然是找第 个数,且
很大(
),我们不能一个一个数去数,必须找规律。
我们考察一下奇数序列,看看哪些是“智数”。
我们需要关注 3 和 5 的最小公倍数。。
但因为我们只看奇数,奇数的周期是 2,所以我们应该观察
范围内的规律。
让我们列出 1 到 30 之间的所有整数,筛选出符合条件的“智数”:
- 1:不是
- 3:是 (3的倍数) -> 第1个
- 5:是 (5的倍数) -> 第2个
- 7:不是
- 9:是 (3的倍数) -> 第3个
- 11:不是
- 13:不是
- 15:是 (3和5的倍数) -> 第4个
- 17:不是
- 19:不是
- 21:是 (3的倍数) -> 第5个
- 23:不是
- 25:是 (5的倍数) -> 第6个
- 27:是 (3的倍数) -> 第7个
- 29:不是
发现规律:
在每 30 个自然数(或者说每15个奇数)的周期里,恰好有 7 个“智数”。
这 7 个数相对于周期的偏移量(Offset)分别是:
{3, 5, 9, 15, 21, 25, 27}
这个规律会无限循环:
- 第 1~7 个智数在 1~30 之间。
- 第 8~14 个智数在 31~60 之间(即
)。
- 以此类推。
现在我们要找第 个智数。我们可以利用周期性直接计算。
-
确定完整的周期数: 每 30 个数里有 7 个智数。 我们可以算出第
个智数经历了多少个完整的“7个一组”。
为了方便计算(处理数组下标从0开始的问题),我们通常使用
来计算:
(注:// 表示整数除法)
-
确定在周期内的位置:
这个余数对应我们在
{3, 5, 9, 15, 21, 25, 27}这个列表中的位置。 -
计算最终结果:
代码实现
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
array<int, 7> v{3, 5, 9, 15, 21, 25, 27};
while (T--) {
int k;
cin >> k;
ll cycle = (k - 1) / 7;
ll idx = (k - 1) % 7;
ll ans = 30LL * cycle + (ll)v[idx];
cout << ans << endl;
}
}
#归纳法#每日一题@牛客网 文章被收录于专栏
牛客网每日一题

