61. 亲和数
题目
问题描述
古希腊数学家毕达哥拉斯在自然数研究中发现,
220的所有真约数(即不是自身的约数)之和为:
1+2+4+5+10+11+20+22+44+55+110=284。
而284的所有真约数为1、2、4、71、 142,加起来恰好为220。
人们对这样的数感到很惊奇,并称之为亲和数。
一般地讲,如果两个数中任何一个数都是另一个数的真约数之和,则这两个数就是亲和数。
你的任务就编写一个程序,判断给定的两个数是否是亲和数。
请定义一个函数,传入一个数n,返回n的所有真约数之和。
输入说明
输入数据第一行包含一个数M,接下来有M行,每行一个实例,包含两个整数A,B; 其中 0 <= A,B <= 600000
输出说明
对于每个测试实例,如果A和B是亲和数的话输出YES,否则输出NO。
个人总结
易错点
需要注意计算总和时的几种情况,大多数情况下因子都是成对增加的,只有两个例外。一个是开头的 1 要加上,但是和它对应的数字 n 本身却不能加上,还有一个是根号因子只应该加一次,而不是加两次。
代码
cpp
#include <bits/stdc++.h>
using namespace std;
int sum_zys(int n) {
int sum = 0;
// 成对寻找因子
int i;
for (i = 1; i * i < n; i++) {
if (n % i == 0) sum += i + n/i;
}
// 根号只加一次
if (i * i == n) sum += i;
// 不要忘记数字自身不算
sum -= n;
return sum;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
int M;
cin >> M;
for (int i = 0; i < M; i++) {
int A, B;
cin >> A >> B;
if (sum_zys(A) == B && sum_zys(B) == A) {
cout << "YES\n";
} else {
cout << "NO\n";
}
}
return 0;
}
62. 分拆素数和
题目
问题描述
把一个偶数拆成两个不同素数的和,有几种拆法呢?
说明:
比如10,可以拆成3+7和5+5以及7+3,
但是3+7与7+3相同,只算一种,5+5由于两个素数相同,不计算在内。
因此,10的拆法只有一种。
输入说明
首先输入一个T(不超过500),然后输入T个正的偶数,其值不会超过10000。
输出说明
对应每个偶数,输出其拆成不同素数的个数,每个结果占一行。
个人总结
思路
预处理素数:由于有多组数据且数值范围较小(10000),先使用bool数组预处理并标记该范围内所有整数是否为素数,提高查询效率。
穷举组合:对于输入的偶数n,从2开始遍历第一个加数i。
计数判断:若i和n-i在预处理数组中均为素数,则计数器加1。
易错点
题目要求两个素数必须"不同"且不计顺序(如3+7和7+3算一种)。因此循环遍历的终止条件必须严格小于n/2。若包含n/2则会统计到相同素数的情况(如5+5),若超过n/2则会造成重复统计。
知识点 - 素数判断优化版
在之前的题目中,我们已经遇到了好几次需要判断素数的题目,也掌握了基础的方法。这次来了解一个更优化的方法,写起来更复杂,但是运行时比普通方法快三倍,可能会在一些场景有用。
先来看代码:
代码模板
cpp
bool isPrime(int n) {
// 1. 处理小于 5 的特殊情况
if (n <= 1) return false;
if (n <= 3) return true; // 2 和 3 是质数
// 2. 预先排除所有 2 的倍数和 3 的倍数
// 如果这一步通过了,说明 n 肯定不是 2 的倍数,也不是 3 的倍数
if (n % 2 == 0 || n % 3 == 0) return false;
// 3. 正式循环
// 从 5 开始试 (因为 2,3,4 都被上面排除了)
// 步长为 6 (i += 6)
for (int i = 5; i * i <= n; i += 6) {
// 检查 i (即 6x-1 或 6x+5 的位置,如 5, 11, 17...)
if (n % i == 0) return false;
// 检查 i+2 (即 6x+1 的位置,如 7, 13, 19...)
if (n % (i + 2) == 0) return false;
}
return true;
}
原理说明
第一步:找出循环规律(周期是 6)
我们要判断一个数 nnn 是不是质数,就是看它能不能被比它小的数整除。 我们先看除数 的规律。任何整数除以 6,余数只有 6 种情况。 我们把所有的自然数写在下面,看看哪些可能是质数(或者质数的因子):
| 形式 | 余数 | 例子 | 说明 | 是否需要检查? |
|---|---|---|---|---|
| 6x | 0 | 6, 12, 18... | 是 6 的倍数(也就是 2 和 3 的倍数) | ❌ 排除 |
| 6x+1 | 1 | 7, 13, 19... | 可能是质数 | ✅ 需要检查 |
| 6x+2 | 2 | 8, 14, 20... | 是 2 的倍数 (2(3x+1)2(3x+1)2(3x+1)) | ❌ 排除 |
| 6x+3 | 3 | 9, 15, 21... | 是 3 的倍数 (3(2x+1)3(2x+1)3(2x+1)) | ❌ 排除 |
| 6x+4 | 4 | 10, 16, 22... | 是 2 的倍数 (2(3x+2)2(3x+2)2(3x+2)) | ❌ 排除 |
| 6x+5 | 5 | 5, 11, 17... | 可能是质数 | ✅ 需要检查 |
结论: 在每 6 个连续的整数里,只有 2 个数(余数为 1 和 5 的)有资格做质数因子。其他的全是 2 或 3 的倍数。
第二步:为什么步长是 6?
如果我们先把 n 对 2 和 3 取模(预处理),确认 n 不是 2 和 3 的倍数,那么我们在循环寻找因子时,就完全不用再试 2 和 3 的倍数了。
我们需要检查的序列是: 5, 7, 11, 13, 17, 19, 23, 25, ...
请注意观察这个序列的间隔:
- 5 到 7 (差 2)
- 7 到 11 (差 4)
- 11 到 13 (差 2)
- 13 到 17 (差 4) ...
间隔是 2, 4, 2, 4... 交替出现的。 写代码时,如果步长一会儿加 2 一会儿加 4,写起来很麻烦。
聪明的写法(步长固定为 6): 我们把 (5, 7) 看作一组,(11, 13) 看作下一组。
- 第一组的开头是 5。
- 第二组的开头是 11。
- 第三组的开头是 17。
发现了吗?组与组的开头,刚好差 6。
所以,我们可以让循环变量 i 每次增加 6,然后在循环内部一次检查两个数:i 和 i+2。
总结
2 和 3 的最小公倍数是 6。
在 6 的周期里,排除了 2 和 3 的倍数后,只剩下 两个位置 (i 和 i+2)。
所以我们每次走 6 步,顺手把这两个位置都查了。
这就是为什么它比普通写法快 3 倍,因为它跳过了所有偶数(占50%)和所有 3 的倍数(占33%,去重后总共跳过了 66.6% 的数),只剩下了 33.3% 的数需要做除法运算。
代码
cpp
#include <bits/stdc++.h>
using namespace std;
// 判断单个数字是否是素数
bool is_prime(int n) {
if (n == 1) return false;
if (n == 2 || n == 3) return true;
if (n % 6 != 5 && n % 6 != 1) return false;
for (int i = 5; i * i <= n; i += 6) {
if (n % i == 0) return false;
if (n % (i + 2) == 0) return false;
}
return true;
}
// 建立是否是素数的数组储存
bool p[10005] = {false};
void init_prime(bool p[]) {
for (int i = 1; i < 10004; i++) {
p[i] = is_prime(i);
}
return;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
int T;
cin >> T;
// 初始化
init_prime(p);
for (int i = 0; i < T; i++) {
int n;
cin >> n;
int cnt = 0;
// 遍历寻找组合
for (int j = 2; j < n/2; j++) {
if (p[j] && p[n - j]) {
cnt++;
} else {
continue;
}
}
cout << cnt << "\n";
}
return 0;
}
63. 歌德巴赫猜想
题目
问题描述
歌德巴赫猜想指出:任何一个大于2的偶数,都可以表示成两个素数的和。例如:8 = 3+5, 44 = 13+31等。试编程在6至100范围内验证歌德巴赫猜想。
输入说明
先输入一个正整数n,表示有n组测试数据。所有数据前后没有多余的空行,两组数据之间也没有多余的空行。每组输入数据由一行组成,在接下来的n行中,每行有1个偶数a(6≤a≤100),在行首和行尾没有多余的空格。
输出说明
对于每组输入,输出满足歌德巴赫猜想两个素数,小的素数的在前,在行首和行尾没有多余的空格。如果有多组结果,输出的第一个素数要求最小。所有数据前后没有多余的空行,两组数据之间也没有多余的空行。
个人总结
和上一题一样的思路
代码
cpp
#include <bits/stdc++.h>
using namespace std;
bool is_prime(int n) {
if (n == 1) return false;
if (n == 2 || n == 3) return true;
if (n % 6 == 1 || n % 6 == 5) {
for (int i = 5; i * i <= n; i += 6) {
if (n % i == 0 || n % (i + 2) == 0) {
return false;
}
}
} else {
return false;
}
return true;
}
bool p[105] = {false};
void init_prime(bool p[]) {
for (int i = 1; i < 100; i++) {
p[i] = is_prime(i);
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
int n;
cin >> n;
for (int i = 0; i < n; i++) {
int a;
cin >> a;
init_prime(p);
for (int j = 2; j < a; j ++) {
if (p[j] && p[a-j]) {
cout << j << " " << a - j << "\n";
break;
}
}
}
return 0;
}
计算机英语翻译练习
- Ubiquitous Computing
Ubiquitous computing is a post-desktop model of human- computer interaction in which information processing is integrated into everyday objects and activities. For daily activities, people may engage in using many pervasive devices simultaneously. They may not even be aware of the existence of the interactive devices. Although the idea is simple, its application is difficult. If all objects in the world were equipped with minuscule identifying devices, daily life on our planet could undergo a major transformation.
- 普适计算
普适计算是后桌面时代的一种人机交互模型,它将信息处理集成进日常物品与活动中。
在日常活动中,人们也许会同时参与使用遍布各处的设备。也许他们甚至不会意识到这些交互设备的存在。
尽管这个想法很简单,但应用起来却很难。如果世界上的所有物体都配备了微型识别设备,这颗星球上的日常生活将会发生巨大的转变。
The loT cannot be realized without systems design and engineering, and user interfaces. Contemporary human- computer interaction models, whether command-line , menu- driven, or GUl-based, are inappropriate and inadequate to meet ubiquitous computing demands. The natural loTparadigm appropriate to a ubiquitous computing world has yet to emerge. Contemporary devices that lend support to ubiquitous computing include smartphones, tablet computers, sensor networks, RFID tags , smart cards, GPS devices, and others. In ubiquitous computing, the loT provides a network of sensor- or radio-connected devices that can be uniquely identified and located in the cyber-physical space. This loT is mostly wirelessly connected as a self-configuring network of radio-frequency tags,low-cost sensors, or e-labels. The term "loT" combines RFID technology with today's IPv6 -based Internet technology. All things (objects) have IP addresses, which can be uniquely identified. The IP-identifiable objects are readable, recognizable, locatable, addressable, and/or controllable via the Internet, aided by RFID, Wi-Fi, ZigBee, mobile networks, and GPS
没有系统设计、系统工程以及用户界面,就无法实现物联网。
当代人机交互模型,无论是通过命令行、菜单还是界面交互,都不适合也不足以满足多变计算需求。能够适应普适计算世界的天然物联网范式尚未出现。
当代支持普世计算的设备有智能手机、笔记本电脑、传感器网络、RFID 标签、智能卡、GPS 设备等等.
在普适计算中,物联网提供了一个由传感器或无线连接设备构成的网络,这些设备在信息物理空间中可以被唯一地识别和定位。
这种物联网主要由射频标签、低成本传感器或电子标签组成的自配置网络无线连接而成。
物联网这个术语结合了 RFID 技术和如今的 IPv6 网络技术。所有的物品都拥有 IP 地址,从而可以被唯一识别。
借助 RFID、Wi-Fi、ZigBee、移动网络和 GPS 的帮助,可识别 IP 的物品在互联网上是可读、可识别、可定位、可寻址,亦或是可控制的。
Il. Enabling and Synergistic Technologies
Many technologies can be applied to build the loT infrastructure and specific loT systems for special application domains. Supportive technologies are divided into two categories. Enabling technologies build up the foundations of the loT. Among the enabling technologies, tracking(RFID), sensor networks,and GPS are critical.
II. 赋能与协同技术
许多技术可用于构建物联网基础设施以及针对特定应用领域的具体物联网系统。
支撑技术分为两类。赋能技术建立了物联网的基础。在赋能技术中,追踪(RFID)、传感器网络和GPS至关重要。
背单词打卡截图
