记录1
#include <bits/stdc++.h>
using namespace std;
bool f(int n){
for(int i=2;i<n;i++){
if(n%i==0) return false;
}
return true;
}
int re(int n){
int m=0,t=0;
while(n){
t=n%10;
m=m*10+t;
n/=10;
}
return m;
}
int main() {
int n,m;
cin>>n>>m;
for(int i=n;i<=m;i++){
if(f(i)&&f(re(i))) cout<<i<<endl;
}
return 0;
}
本题思路
- 判断素数
- 转换数字
判断素数
因为有数据保证
输入 1 行,包含两个正整数 A 和 B。保证 10<A<B<100。
所以可以直接考虑两位数情况
bool f(int n){
for(int i=2;i<n;i++){
if(n%i==0) return false;
}
return true;
}
补充:6k±1优化法判断素数
bool isPrime6k(int n) {
if (n <= 1) return false;
if (n <= 3) return true;
if (n % 2 == 0 || n % 3 == 0) return false;
for (int i = 5; i * i <= n; i += 6) {
if (n % i == 0 || n % (i + 2) == 0) return false;
}
return true;
}
6k±1优化法的数学原理
所有大于3的素数均可以表示为6k±1的形式(其中k为正整数)。这一特性源于数论中对整数模6的分类:
- 任何整数n模6的余数只能是0、1、2、3、4或5。
- 若n ≡ 0、2、4 (mod 6),则n为偶数,大于2时必为合数。
- 若n ≡ 3 (mod 6),则n为3的倍数,大于3时必为合数。
- 仅当n ≡ 1或5 (mod 6)时,n可能是素数(5 ≡ -1 mod 6,故统一表示为6k±1)。
减少检查次数的原因
传统素数检查需试除所有小于√n的整数,而6k±1法通过数学性质排除了以下情况:
- 无需检查偶数(2的倍数)。
- 无需检查3的倍数。
- 仅需检查6k±1形式的数,即每6个数中仅检查2个候选。
例如,检查n=37是否为素数:
- 常规方法需试除2、3、4、5、6(共5次)。
- 6k±1法仅需试除5(=6×1-1)和7(=6×1+1,但7²>37),实际只需检查5(1次)。
实现效率提升
对于大数n,检查次数从O(√n)降低到O(√n/3),因为:
- 原始方法需√n次检查。
- 优化后仅需检查1/3的数(6k±1占全部数的1/3)。
公式化表达为: 检查范围缩减至:k ≤ ⌊√n/6⌋
每次k生成两个候选除数:6k−1和6k+1。
转换数字
int re(int n){
int m=0,t=0;
while(n){
t=n%10;
m=m*10+t;
n/=10;
}
return m;
}
简单的数位分离,%10相当于拿出数的尾巴,/10相当于砍掉数的尾巴
倒过来时候,通过乘10来进行扩大数的位数,然后加上尾巴数
补充
在算法竞赛和编程中,处理素数是常见的任务。以下是一些常用的处理素数的方法,条理清晰,分级明确,帮助你更好地理解和应用这些方法。
1. 判断一个数是否为素数
1.1 方法1:暴力法
步骤:
检查从2到 n 的所有数是否能整除 n。
如果没有找到能整除 n 的数,则 n 是素数。
代码示例:
#include <iostream> #include <cmath> using namespace std; bool isPrime(int n) { if (n <= 1) return false; if (n <= 3) return true; if (n % 2 == 0 || n % 3 == 0) return false; for (int i = 5; i * i <= n; i += 6) { if (n % i == 0 || n % (i + 2) == 0) return false; } return true; } int main() { int n; cout << "Enter a number: "; cin >> n; if (isPrime(n)) { cout << n << " is a prime number." << endl; } else { cout << n << " is not a prime number." << endl; } return 0; }2. 生成一定范围内的所有素数
2.1 方法1:埃拉托斯特尼筛法(Sieve of Eratosthenes)
步骤:
创建一个布尔数组
is_prime,大小为 n+1,并将所有元素初始化为true。将0和1标记为
false。从2开始,逐步标记所有素数的倍数为
false。遍历数组,所有值为
true的索引即为素数。代码示例:
#include <iostream> #include <vector> using namespace std; vector<int> sieveOfEratosthenes(int n) { vector<bool> is_prime(n + 1, true); is_prime[0] = is_prime[1] = false; for (int i = 2; i * i <= n; i++) { if (is_prime[i]) { for (int j = i * i; j <= n; j += i) { is_prime[j] = false; } } } vector<int> primes; for (int i = 2; i <= n; i++) { if (is_prime[i]) { primes.push_back(i); } } return primes; } int main() { int n; cout << "Enter the upper limit: "; cin >> n; vector<int> primes = sieveOfEratosthenes(n); cout << "Prime numbers up to " << n << " are:" << endl; for (int prime : primes) { cout << prime << " "; } cout << endl; return 0; }3. 计算一定范围内的素数个数
3.1 方法1:使用埃拉托斯特尼筛法
步骤:
使用埃拉托斯特尼筛法生成所有素数。
计算素数的个数。
代码示例:
#include <iostream> #include <vector> using namespace std; int countPrimes(int n) { vector<bool> is_prime(n + 1, true); is_prime[0] = is_prime[1] = false; for (int i = 2; i * i <= n; i++) { if (is_prime[i]) { for (int j = i * i; j <= n; j += i) { is_prime[j] = false; } } } int count = 0; for (int i = 2; i <= n; i++) { if (is_prime[i]) { count++; } } return count; } int main() { int n; cout << "Enter the upper limit: "; cin >> n; cout << "Number of prime numbers up to " << n << " is: " << countPrimes(n) << endl; return 0; }4. 分解质因数
4.1 方法1:试除法
步骤:
从2开始,逐步尝试除以 n。
如果能整除,记录该质因数,并将 n 除以该质因数。
重复上述步骤,直到 n 为1。
代码示例:
#include <iostream> #include <vector> using namespace std; vector<pair<int, int>> primeFactors(int n) { vector<pair<int, int>> factors; for (int i = 2; i * i <= n; i++) { if (n % i == 0) { int count = 0; while (n % i == 0) { n /= i; count++; } factors.push_back({i, count}); } } if (n > 1) { factors.push_back({n, 1}); } return factors; } int main() { int n; cout << "Enter a number: "; cin >> n; vector<pair<int, int>> factors = primeFactors(n); cout << "Prime factors of " << n << " are:" << endl; for (const auto& factor : factors) { cout << factor.first << "^" << factor.second << " "; } cout << endl; return 0; }5. 计算欧拉函数
5.1 方法1:使用质因数分解
步骤:
分解 n 的质因数。
使用欧拉函数公式计算 ϕ(n)。
代码示例:
#include <iostream> #include <vector> using namespace std; int eulerPhi(int n) { vector<pair<int, int>> factors = primeFactors(n); double result = n; for (const auto& factor : factors) { result *= (1.0 - (1.0 / factor.first)); } return static_cast<int>(result); } int main() { int n; cout << "Enter a number: "; cin >> n; cout << "Euler's Totient Function of " << n << " is: " << eulerPhi(n) << endl; return 0; }6. 计算最大公约数(GCD)
6.1 方法1:欧几里得算法
步骤:
使用欧几里得算法递归计算最大公约数。
代码示例:
#include <iostream> using namespace std; int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); } int main() { int a, b; cout << "Enter two numbers: "; cin >> a >> b; cout << "GCD of " << a << " and " << b << " is: " << gcd(a, b) << endl; return 0; }7. 计算最小公倍数(LCM)
7.1 方法1:使用GCD
步骤:
使用GCD计算LCM。
代码示例:
#include <iostream> using namespace std; int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); } int lcm(int a, int b) { return a / gcd(a, b) * b; } int main() { int a, b; cout << "Enter two numbers: "; cin >> a >> b; cout << "LCM of " << a << " and " << b << " is: " << lcm(a, b) << endl; return 0; }总结
判断素数:使用暴力法或优化的试除法。
生成素数:使用埃拉托斯特尼筛法。
计算素数个数:使用埃拉托斯特尼筛法。
分解质因数:使用试除法。
计算欧拉函数:使用质因数分解。
计算最大公约数:使用欧几里得算法。
计算最小公倍数:使用GCD。
这些方法在处理素数相关问题时非常有效。
1131

被折叠的 条评论
为什么被折叠?



