【入门】寻找雷劈数

【入门】寻找雷劈数

题意分析:

这道题的题目还是比较明了的,这里就不做过多解释了。

解题思路:

截取出来后根据题目要求判断。

算法分析:

用for语句在1000到9999之间循环,

把千位+百位和十位+个位截取出来,

再根据题目进行判断。

答案参考:

var

i,ab,cd:longint;

begin

for i:=1000 to 9999 do      //循环

begin

ab:=i div 100;

cd:=i mod 100;

if (ab+cd)*(ab+cd)=i then    //判断

writeln(i);

end;

end.

雷劈是指一个如果是合,而且它的因子中含有“雷劈因子”(即7),则称这个为“雷劈”。根据定义,我们可以得到一个暴力的算法:枚举每个,然后判断它是否是合,再判断它的因子中是否包含7。但这个算法显然是不可取的,因为它的时间复杂度是 $O(n\sqrt{n})$,无法通过本题的大据测试。 实际上,我们可以根据“雷劈因子”的性质,设计一种更高效的算法。我们可以先枚举所有包含“雷劈因子”的字,然后对它们的倍进行标记,标记完成后,没有被标记的就是“雷劈”。 具体实现的过程是: 1.首先标记7的倍,即将它们的值全部置为1,表示它们不是“雷劈”。 2.然后标记其他包含“雷劈因子”的字的倍,比如 14、17、21、27、28、35 等等。这些字可以表示成 $7k+r$ 的形式,其中 $r$ 是 $1,2,4$ 中的一个。我们枚举 $r$,然后计算 $k$ 的取值范围,对于每个 $k$,将 $7k+r$ 倍的值置为1,表示它们不是“雷劈”。 3.最后,没有被标记的就是“雷劈”。 下面是一个实现: ```c #include <stdio.h> #include <string.h> #define MAX_N 1000000 char is_not_prime[MAX_N + 1]; int main() { memset(is_not_prime, 0, sizeof is_not_prime); is_not_prime[0] = is_not_prime[1] = 1; for (int i = 2; i <= MAX_N; i++) { if (!is_not_prime[i]) { if (i % 7 == 0) { // 7 的倍不是雷劈 is_not_prime[i] = 1; } else { for (int j = 1; j <= 3; j++) { // 遍历 r = 1, 2, 4 int x = i * 7 + j; if (x <= MAX_N) { // 防止越界 is_not_prime[x] = 1; } } } } } for (int i = 1; i <= MAX_N; i++) { if (!is_not_prime[i]) { printf("%d\n", i); } } return 0; } ``` 这里使用一个布尔组 `is_not_prime` 来标记每个是否是“雷劈”。组初始化为0,表示每个都不是“雷劈”。然后按照前面的算法,对于包含“雷劈因子”的字,将它们的倍标记为1,表示它们不是“雷劈”。最后,遍历组,输出没有被标记的,即为“雷劈”。 由于最大目可能达到1000000,我们需要使用一个布尔组来标记每个,以节省空间。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值