与 7 无关的数 的题解
记住只在没有思路时使用题解,不要从它复制粘贴代码。请尊重题目和题解的作者。
在解题之前提交题解的代码会导致封禁。
在解题之前提交题解的代码会导致封禁。
作者:
概述
本题要求计算 到
之间所有与
无关的正整数的平方和,其中“与
无关”指数不能被
整除,且十进制表示的每一位都不是
。核心解法是从
到
逐个枚举,对每个数做整除与取模判定,把无关的数平方后累加。
分析
核心观察
一个数是否与 相关由两件事决定:它对
取模的结果,以及它的十进制各位数字。题面限制
,因此参与判定的每个数至多两位,“某一位上是
” 只需检查个位与十位这两个位置。
思路
记 为满足条件的正整数集合:
记答案为 ,要求的就是
三个判定条件之间是或的关系:i % 7 == 0 对应“能被 整除”,
i % 10 == 7 对应个位是 ,
i / 10 % 10 == 7 对应十位是 。命中任意一条即为相关,跳过;三条都不命中才把
累加进答案。
也可以先把 的相关性一次筛出来做前缀和,但每个数判定的代价已经是
,枚举一遍总时间
,筛法并不会带来量级上的改进,反而多占一份标记数组,因此直接枚举即可。
平方和规模也需要确认:即使 全部计入,
,远远小于
,32 位有符号整型足以容纳。
具体示例
以样例 为例。被
整除的数有
,数位上含
的数有
,合并后与
相关的数是
四个,剩余
个正整数与
无关:
依次累加它们的平方:,
,
,
,
,合计
,与样例输出一致。
注意 虽然不被
整除,但个位是
,同样要被排除;而
不含数字
,却因被
整除也要排除。两类条件缺一不可。
算法步骤
- 读入
n,令累加变量ans为。
- 从
到
依次枚举
i。 - 若
i % 7 == 0、i % 10 == 7、i / 10 % 10 == 7三者中任意一条成立,说明i与相关,跳过。
- 否则令
ans加上i * i。 - 输出
ans。
复杂度分析
- 时间:
。枚举
个数,每个数只做常数次整除、取模与比较。
- 空间:
。只需要
n、i、ans三个整型变量,不需要保存任何序列。
实现注意事项
- 三条判定是“或”的关系,命中任意一条即为相关;只有全部不命中才计入答案,取反时不要把三个条件写成与。
- 十位必须单独检查,只写
i % 7 == 0 || i % 10 == 7会漏掉这一类十位为
的数。
- 题面限制
,所以
至多两位,
i / 10 % 10就是十位;若把范围推广到任意位数,需要改成逐位取模的循环或直接转字符串判断。 - 平方和上界为
,
int足够;即便写成i * i也不会溢出,因为单个时
。
,循环从
开始;不存在答案为空的输入,不需要特判。
- 输入只有一个整数,用
cin直接读入即可,无需按行处理。
源代码
#include <iostream>
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n;
std::cin >> n;
int ans = 0;
for (int i = 1; i <= n; ++i) {
// 与 7 相关:能被 7 整除,或个位是 7,或十位是 7
if (i % 7 == 0 || i % 10 == 7 || i / 10 % 10 == 7) {
continue;
}
ans += i * i;
}
std::cout << ans << '\n';
return 0;
}
import sys
def main():
n = int(sys.stdin.buffer.read().split()[0])
ans = 0
for i in range(1, n + 1):
if i % 7 == 0 or i % 10 == 7 or i // 10 % 10 == 7:
continue
ans += i * i
sys.stdout.write(str(ans) + "\n")
main()
评论