#CSPJCSMN08. 普及组程序专项-数学:质数
普及组程序专项-数学:质数
普及组质数专题训练(10题精选)
题目1:基础质数判断(简单)
1 #include <iostream>
2 #include <cmath>
3 using namespace std;
4
5 bool isPrime(int n) {
6 if (n <= 1) return false;
7 for (int i = 2; i <= sqrt(n); i++) {
8 if (n % i == 0) return false;
9 }
10 return true;
11 }
12
13 int main() {
14 int n;
15 cin >> n;
16
17 if (isPrime(n)) {
18 cout << n << "是质数" << endl;
19 } else {
20 cout << n << "不是质数" << endl;
21 }
22
23 return 0;
24 }
选择题
-
如果将第7行的
i <= sqrt(n)改为i < n,输入n=100时,循环次数会:( )
A. 从10次增加到100次
B. 从10次减少到9次
C. 保持不变
D. 程序出错 -
第6行
if (n <= 1) return false;的作用不包括:( )
A. 处理n=0的情况
B. 处理n=1的情况
C. 处理n=2的情况
D. 处理n为负数的情况 -
如果要优化算法,可以在第7行前添加代码快速排除偶数,以下哪段代码合适?( )
A.if (n == 2) return true;
B.if (n % 2 == 0) return n == 2;
C.if (n < 2) return false;
D. 以上都可以 -
第8行的
n % i == 0检查n是否能被i整除,如果改为n % i != 0,会导致:( )
A. 算法结果反转(质数判断为合数,合数判断为质数)
B. 所有数都被判断为质数
C. 所有数都被判断为合数
D. 程序死循环 -
如果将第7行改为
for (int i = 2; i * i <= n; i++),有什么优点?( )
A. 避免浮点数运算
B. 提高精度
C. 减少循环次数
D. 以上都是
题目2:质因数分解(简单)
1 #include <iostream>
2 #include <vector>
3 using namespace std;
4
5 vector<int> primeFactors(int n) {
6 vector<int> factors;
7
8 for (int i = 2; i * i <= n; i++) {
9 while (n % i == 0) {
10 factors.push_back(i);
11 n /= i;
12 }
13 }
14
15 if (n > 1) {
16 factors.push_back(n);
17 }
18
19 return factors;
20 }
21
22 int main() {
23 int n;
24 cin >> n;
25
26 vector<int> factors = primeFactors(n);
27
28 cout << n << " = ";
29 for (int i = 0; i < factors.size(); i++) {
30 if (i > 0) cout << " × ";
31 cout << factors[i];
32 }
33 cout << endl;
34
35 return 0;
36 }
选择题
-
第8行
i * i <= n的循环条件,当n=13时,循环次数是:( )
A. 0次
B. 1次
C. 2次
D. 13次 -
第9-12行的while循环如果改为if,输入n=8时,输出是:( )
A. 8 = 2 × 2 × 2
B. 8 = 2 × 4
C. 8 = 2
D. 8 = 8 -
第15-17行的if语句处理什么情况?( )
A. 处理n本身就是质数的情况
B. 处理n大于1的剩余部分
C. 都是
D. 都不是 -
如果将第8行改为
for (int i = 2; i <= n; i++),对n=100的影响是:( )
A. 循环次数从10次增加到100次
B. 循环次数从10次减少到9次
C. 结果可能错误
D. 没有影响 -
第9行的
n % i == 0中,当i=4时,能否进入循环?( )
A. 能,如果n是4的倍数
B. 不能,因为4不是质数
C. 不能,因为循环不会检查i=4
D. 不确定
题目3:埃拉托斯特尼筛法(中等)
1 #include <iostream>
2 #include <vector>
3 using namespace std;
4
5 vector<int> sieveOfEratosthenes(int n) {
6 vector<bool> isPrime(n + 1, true);
7 vector<int> primes;
8
9 isPrime[0] = isPrime[1] = false;
10
11 for (int i = 2; i * i <= n; i++) {
12 if (isPrime[i]) {
13 for (int j = i * i; j <= n; j += i) {
14 isPrime[j] = false;
15 }
16 }
17 }
18
19 for (int i = 2; i <= n; i++) {
20 if (isPrime[i]) {
21 primes.push_back(i);
22 }
23 }
24
25 return primes;
26 }
27
28 int main() {
29 int n;
30 cin >> n;
31
32 vector<int> primes = sieveOfEratosthenes(n);
33
34 cout << "小于等于" << n << "的质数有: ";
35 for (int prime : primes) {
36 cout << prime << " ";
37 }
38 cout << endl;
39
40 return 0;
41 }
选择题
-
第13行的
j = i * i而不是j = 2 * i,主要原因是:( )
A. 避免重复标记
B. 提高效率
C. 两者都是
D. 代码更简洁 -
当n=30时,第11行外层循环的i值不会超过:( )
A. 5
B. 6
C. 30
D. 15 -
如果将第13行改为
for (int j = 2 * i; j <= n; j += i),算法会:( )
A. 结果正确但效率降低
B. 结果错误
C. 效率提高
D. 死循环 -
第19-23行的循环收集质数,如果将第20行的
isPrime[i]改为true,会:( )
A. 输出所有数字
B. 输出所有质数
C. 输出所有合数
D. 程序崩溃 -
第6行
vector<bool> isPrime(n + 1, true)创建了大小为n+1的布尔数组,初始化值为true,这个操作的时间复杂度是:( )
A. O(1)
B. O(n)
C. O(n²)
D. O(log n)
题目4:线性筛法(欧拉筛)(中等偏难)
1 #include <iostream>
2 #include <vector>
3 using namespace std;
4
5 vector<int> linearSieve(int n) {
6 vector<bool> isPrime(n + 1, true);
7 vector<int> primes;
8
9 isPrime[0] = isPrime[1] = false;
10
11 for (int i = 2; i <= n; i++) {
12 if (isPrime[i]) {
13 primes.push_back(i);
14 }
15
16 for (int j = 0; j < primes.size() && i * primes[j] <= n; j++) {
17 isPrime[i * primes[j]] = false;
18 if (i % primes[j] == 0) {
19 break;
20 }
21 }
22 }
23
24 return primes;
25 }
26
27 int main() {
28 int n;
29 cin >> n;
30
31 vector<int> primes = linearSieve(n);
32
33 cout << "小于等于" << n << "的质数有: ";
34 for (int prime : primes) {
35 cout << prime << " ";
36 }
37 cout << endl;
38
39 return 0;
40 }
选择题
-
第18行的
if (i % primes[j] == 0) break;作用是什么?( )
A. 保证每个合数只被最小质因子标记
B. 提前结束循环提高效率
C. 避免重复标记
D. 以上都是 -
当i=4时,第16行的内层循环会标记哪些数为合数?( )
A. 4×2=8
B. 8
C. 8和12
D. 8, 12, 16 -
如果不加第18-20行的break,算法会:( )
A. 某些合数被多次标记
B. 算法仍然正确但效率降低
C. 可能漏掉某些合数
D. 程序崩溃 -
第16行的循环条件
j < primes.size() && i * primes[j] <= n中,如果去掉第一个条件,当primes为空时会:( )
A. 访问primes[0]导致段错误
B. 循环不会执行
C. 编译器报错
D. 没有影响 -
线性筛法与埃氏筛相比,主要优点是:( )
A. 每个合数只标记一次
B. 时间复杂度更低
C. 空间复杂度更低
D. 代码更简单
题目5:质因数分解优化(中等)
1 #include <iostream>
2 #include <vector>
3 using namespace std;
4
5 vector<pair<int, int>> primeFactorsWithCount(int n) {
6 vector<pair<int, int>> factors;
7
8 for (int i = 2; i * i <= n; i++) {
9 if (n % i == 0) {
10 int count = 0;
11 while (n % i == 0) {
12 count++;
13 n /= i;
14 }
15 factors.push_back({i, count});
16 }
17 }
18
19 if (n > 1) {
20 factors.push_back({n, 1});
21 }
22
23 return factors;
24 }
25
26 int main() {
27 int n;
28 cin >> n;
29
30 vector<pair<int, int>> factors = primeFactorsWithCount(n);
31
32 cout << n << " = ";
33 for (int i = 0; i < factors.size(); i++) {
34 if (i > 0) cout << " × ";
35 cout << factors[i].first;
36 if (factors[i].second > 1) {
37 cout << "^" << factors[i].second;
38 }
39 }
40 cout << endl;
41
42 return 0;
43 }
选择题
-
第11-14行的while循环记录质因数的指数,如果改为if,输入n=8时,count的值是:( )
A. 0
B. 1
C. 3
D. 8 -
第15行
factors.push_back({i, count})创建了一个pair,这可以替换为:( )
A.factors.push_back(make_pair(i, count))
B.factors.emplace_back(i, count)
C. 都可以
D. 都不能 -
第19-21行处理剩余的大于1的n,这个n一定是:( )
A. 质数
B. 合数
C. 1
D. 不确定 -
第36-38行输出指数,如果指数为1则不输出指数,这行代码可以简化为:( )
A.if (factors[i].second - 1) cout << "^" << factors[i].second;
B.cout << (factors[i].second > 1 ? "^" + to_string(factors[i].second) : "");
C. 都可以
D. 都不能 -
如果将第8行改为
for (int i = 2; i <= n; i++),对n=1000000的影响是:( )
A. 循环次数从1000次增加到1000000次
B. 循环次数从1000次减少到100次
C. 结果可能错误
D. 没有影响
题目6:米勒-拉宾素性测试(难)
1 #include <iostream>
2 #include <cmath>
3 using namespace std;
4
5 long long power(long long a, long long d, long long n) {
6 long long result = 1;
7 a = a % n;
8
9 while (d > 0) {
10 if (d % 2 == 1) {
11 result = (result * a) % n;
12 }
13 a = (a * a) % n;
14 d /= 2;
15 }
16
17 return result;
18 }
19
20 bool millerTest(long long d, long long n) {
21 long long a = 2 + rand() % (n - 4);
22 long long x = power(a, d, n);
23
24 if (x == 1 || x == n - 1) {
25 return true;
26 }
27
28 while (d != n - 1) {
29 x = (x * x) % n;
30 d *= 2;
31
32 if (x == 1) return false;
33 if (x == n - 1) return true;
34 }
35
36 return false;
37 }
38
39 bool isPrimeMillerRabin(long long n, int k) {
40 if (n <= 1 || n == 4) return false;
41 if (n <= 3) return true;
42
43 long long d = n - 1;
44 while (d % 2 == 0) {
45 d /= 2;
46 }
47
48 for (int i = 0; i < k; i++) {
49 if (!millerTest(d, n)) {
50 return false;
51 }
52 }
53
54 return true;
55 }
56
57 int main() {
58 long long n;
59 cin >> n;
60
61 if (isPrimeMillerRabin(n, 5)) {
62 cout << n << "可能是质数" << endl;
63 } else {
64 cout << n << "是合数" << endl;
65 }
66
67 return 0;
68 }
选择题
-
第5-18行的power函数实现了什么算法?( )
A. 快速幂算法
B. 模幂运算
C. 快速幂取模
D. 以上都是 -
第10行的
if (d % 2 == 1)可以替换为:( )
A.if (d & 1)
B.if (d % 2)
C. 都可以
D. 都不能 -
第21行生成随机数a,范围是2到n-2,如果n很小(如n=5),
n-4可能为:( )
A. 1
B. 负数
C. 0
D. 不确定 -
第28-34行的while循环中,d最终会变为n-1,这是因为:( )
A. 每次循环d乘以2
B. 初始d是n-1的奇数部分
C. 循环条件确保d最终等于n-1
D. 以上都是 -
第40行
if (n <= 1 || n == 4) return false;中,为什么要单独处理n=4?( )
A. 4是合数但不是奇数
B. 4会导致随机数生成错误
C. 4在后续测试中可能被误判
D. 没有特别原因
题目7:区间质数统计(中等)
1 #include <iostream>
2 #include <vector>
3 #include <cmath>
4 using namespace std;
5
6 int countPrimesInRange(int a, int b) {
7 if (b < 2) return 0;
8 a = max(a, 2);
9
10 int n = b - a + 1;
11 vector<bool> isPrime(n, true);
12
13 int sqrt_b = sqrt(b);
14 vector<bool> isPrimeSmall(sqrt_b + 1, true);
15 vector<int> primes;
16
17 for (int i = 2; i <= sqrt_b; i++) {
18 if (isPrimeSmall[i]) {
19 primes.push_back(i);
20 for (int j = i * i; j <= sqrt_b; j += i) {
21 isPrimeSmall[j] = false;
22 }
23 }
24 }
25
26 for (int p : primes) {
27 int start = max(p * p, (a + p - 1) / p * p);
28 for (int j = start; j <= b; j += p) {
29 if (j >= a) {
30 isPrime[j - a] = false;
31 }
32 }
33 }
34
35 int count = 0;
36 for (int i = 0; i < n; i++) {
37 if (isPrime[i]) {
38 count++;
39 }
40 }
41
42 return count;
43 }
44
45 int main() {
46 int a, b;
47 cin >> a >> b;
48
49 int count = countPrimesInRange(a, b);
50 cout << "区间[" << a << ", " << b << "]内的质数个数: " << count << endl;
51
52 return 0;
53 }
选择题
-
第27行的
(a + p - 1) / p * p计算的是:( )
A. 大于等于a的最小p的倍数
B. 小于等于a的最大p的倍数
C. a除以p的商
D. a除以p的余数 -
第30行的
isPrime[j - a]中j - a的作用是:( )
A. 将区间[a,b]映射到[0,n-1]
B. 计算索引偏移
C. 避免数组越界
D. 以上都是 -
第13行计算
sqrt_b = sqrt(b),如果改为int sqrt_b = (int)sqrt((double)b),会:( )
A. 更明确类型转换
B. 提高精度
C. 没有区别
D. 可能出错 -
第17-24行生成小质数,如果区间很大但b很小,这部分开销:( )
A. 可以忽略
B. 仍然很大
C. 与a无关
D. 与区间长度无关 -
第28行的循环
for (int j = start; j <= b; j += p),如果p很大,start可能超过b,此时循环:( )
A. 不会执行
B. 执行一次
C. 死循环
D. 段错误
题目8:质数间距问题(难)
1 #include <iostream>
2 #include <vector>
3 #include <cmath>
4 #include <climits>
5 using namespace std;
6
7 vector<int> findPrimes(int n) {
8 vector<bool> isPrime(n + 1, true);
9 vector<int> primes;
10
11 isPrime[0] = isPrime[1] = false;
12 for (int i = 2; i <= n; i++) {
13 if (isPrime[i]) {
14 primes.push_back(i);
15 for (int j = i * i; j <= n; j += i) {
16 isPrime[j] = false;
17 }
18 }
19 }
20
21 return primes;
22 }
23
24 pair<int, int> closestPrimes(int n) {
25 vector<int> primes = findPrimes(n);
26
27 if (primes.size() < 2) {
28 return {-1, -1};
29 }
30
31 int minGap = INT_MAX;
32 pair<int, int> result;
33
34 for (int i = 1; i < primes.size(); i++) {
35 int gap = primes[i] - primes[i - 1];
36 if (gap < minGap) {
37 minGap = gap;
38 result = {primes[i - 1], primes[i]};
39 }
40 }
41
42 return result;
43 }
44
45 int main() {
46 int n;
47 cin >> n;
48
49 auto result = closestPrimes(n);
50
51 if (result.first == -1) {
52 cout << "范围内质数不足2个" << endl;
53 } else {
54 cout << "最接近的质数对: " << result.first << " 和 " << result.second << endl;
55 cout << "它们之间的差距: " << result.second - result.first << endl;
56 }
57
58 return 0;
59 }
选择题
-
第15行的
j = i * i可能溢出,当i很大时,可以如何修改?( )
A. 改为j = 2 * i
B. 添加判断if (i <= n / i) for (int j = i * i; j <= n; j += i)
C. 使用long long类型
D. 以上都可以 -
第27-29行处理特殊情况,如果primes为空,函数返回:( )
A. {-1, -1}
B. {0, 0}
C. 程序崩溃
D. 不确定 -
第31行的
INT_MAX来自哪个头文件?( )
A.<climits>
B.<limits>
C.<cstdlib>
D.<iostream> -
第36行的
if (gap < minGap)如果改为if (gap <= minGap),会:( )
A. 返回最后一对最小间距的质数
B. 返回第一对最小间距的质数
C. 结果可能不同
D. 没有区别 -
第38行的
result = {primes[i - 1], primes[i]}创建pair,这可以替换为:( )
A.result = make_pair(primes[i - 1], primes[i])
B.result.first = primes[i - 1]; result.second = primes[i];
C. 都可以
D. 都不能
题目9:哥德巴赫猜想验证(中等)
1 #include <iostream>
2 #include <vector>
3 using namespace std;
4
5 vector<bool> sieve(int n) {
6 vector<bool> isPrime(n + 1, true);
7 isPrime[0] = isPrime[1] = false;
8
9 for (int i = 2; i * i <= n; i++) {
10 if (isPrime[i]) {
11 for (int j = i * i; j <= n; j += i) {
12 isPrime[j] = false;
13 }
14 }
15 }
16
17 return isPrime;
18 }
19
20 pair<int, int> goldbachConjecture(int n) {
21 if (n < 4 || n % 2 != 0) {
22 return {-1, -1};
23 }
24
25 vector<bool> isPrime = sieve(n);
26
27 for (int i = 2; i <= n / 2; i++) {
28 if (isPrime[i] && isPrime[n - i]) {
29 return {i, n - i};
30 }
31 }
32
33 return {-1, -1};
34 }
35
36 int main() {
37 int n;
38 cin >> n;
39
40 auto result = goldbachConjecture(n);
41
42 if (result.first == -1) {
43 cout << n << "不能表示为两个质数之和" << endl;
44 } else {
45 cout << n << " = " << result.first << " + " << result.second << endl;
46 }
47
48 return 0;
49 }
选择题
-
第21行的
if (n < 4 || n % 2 != 0)处理了哪些无效输入?( )
A. n小于4
B. n是奇数
C. 都是
D. 都不是 -
第27行的循环条件
i <= n / 2而不是i < n,主要为了:( )
A. 避免重复(如3+5和5+3)
B. 提高效率
C. 两者都是
D. 没有特别原因 -
第28行的
isPrime[n - i]可能会访问数组的哪个位置?( )
A. 0到n之间
B. 0到n/2之间
C. n/2到n之间
D. 都有可能 -
如果找到多个解,这个算法返回:( )
A. 第一个找到的解
B. 最后一个找到的解
C. 所有解
D. 最小的解 -
第25行调用sieve(n)生成质数表,如果n很大但只需要验证一个数,可以如何优化?( )
A. 只生成到n/2的质数表
B. 使用更快的质数判断函数
C. 使用概率性质数测试
D. 以上都可以
题目10:回文质数(中等)
1 #include <iostream>
2 #include <vector>
3 #include <cmath>
4 using namespace std;
5
6 bool isPalindrome(int n) {
7 int original = n;
8 int reversed = 0;
9
10 while (n > 0) {
11 reversed = reversed * 10 + n % 10;
12 n /= 10;
13 }
14
15 return original == reversed;
16 }
17
18 bool isPrime(int n) {
19 if (n <= 1) return false;
20 for (int i = 2; i <= sqrt(n); i++) {
21 if (n % i == 0) return false;
22 }
23 return true;
24 }
25
26 vector<int> findPalindromicPrimes(int n) {
27 vector<int> result;
28
29 for (int i = 2; i <= n; i++) {
30 if (isPalindrome(i) && isPrime(i)) {
31 result.push_back(i);
32 }
33 }
34
35 return result;
36 }
37
38 int main() {
39 int n;
40 cin >> n;
41
42 vector<int> primes = findPalindromicPrimes(n);
43
44 cout << "小于等于" << n << "的回文质数: ";
45 for (int prime : primes) {
46 cout << prime << " ";
47 }
48 cout << endl;
49
50 return 0;
51 }
选择题
-
第10-13行的while循环反转数字,如果n=123,循环结束后reversed的值是:( )
A. 321
B. 123
C. 0
D. 32 -
第30行的条件
isPalindrome(i) && isPrime(i),如果交换顺序为isPrime(i) && isPalindrome(i),会:( )
A. 提高效率,因为质数判断更耗时
B. 降低效率
C. 结果错误
D. 没有影响 -
第20行的
i <= sqrt(n)可以优化,以下哪项不是优化方法?( )
A. 改为i * i <= n
B. 先判断偶数
C. 从3开始,步长为2
D. 使用质数表 -
第6-16行的isPalindrome函数对于负数会:( )
A. 返回false
B. 进入无限循环
C. 返回true
D. 不确定 -
第29行的循环从2开始,如果n很大,可以如何优化?( )
A. 只检查奇数位回文数
B. 生成回文数再判断质数
C. 使用更快的质数判断
D. 以上都可以