某个整数很长很长,形如:1232123212321……,其规律是从 1 开始逐一升高到 3 然后逐一降低到 1,然后又逐一升高到 3,一直到很长很长。假设最高位编号为 1,要求判断从左边最高位开始的第 位数是几?在横线处应该填入的代码是( )。
01int N, M; 02cout << "请输入编号:"; 03cin >> N; 04M = ____________; 05if (M != 0) 06 cout << M; 07else 08 cout << 2;
A: N%4。序列1,2,3,2循环,N%4=0对应2,=1,2,3分别1,2,3。规律周期4
以内最大的素数是( )。
D:97。100 以内素数末尾必为 1/3/7/9,逐一筛除合数后最大为 97;89 是素数但小于 97,91=7×13、93=3×31 为合数,故排除。
和 的最大公约数是( )。
A:29。辗转相除:377=319×1+58,319=58×5+29,58=29×2+0;余数为 0 时的除数 29 即最大公约数。
下面 C++ 代码用于判断 N(大于等于 2 的正整数)是否为质数(素数)。下面对如下代码的说法,正确的是( )。
01cin >> N; 02for (i = 2; i < N / 2; i++) 03 if (N % i == 0) { 04 cout << N << "不是质数"; 05 break; 06 } 07if (i >= N / 2) 08 cout << N << "是质数";
D: 应改为N/2+1。N/2当N=2时为1,i<1不进但N=2是质数,边界bug
阅读下面的 C++ 代码,其中变量都是整型,则说法正确的是( )。
01cin >> a >> b; 02while (b != 0){ 03 remainder = a % b; 04 a = b; 05 b = remainder; 06} 07cout << a;
(链环重量: G3/G4/G6每9环循环,part1=N%9应为0..8, part2=N%9+1. 描述"必须同时修改L1和L2"正确 → A)
闰年的定义:
下面程序是判断是否是闰年的正确程序。
01cin >> n; 02cout << ((n % 4 == 0 && n % 100 != 0) || (n % 400 == 0) ? 1 : 0); 03return 0;
正确。闰年判断4的倍数且非100倍数或400倍数
以下 C++ 代码用于实现每个整数对应的因数,如输入 ,则输出 1 2 3 4 6 12;如输入 ,则输出 1 2 3 6 9 18。横线处应填入代码是( )。
01int n; 02cin>>n; 03for(int i=1;i<=n;i++) 04{ 05 ____________ 06 { 07 cout<<i<<" "; 08 } 09}
A:if(n%i==0)。遍历 i=1..n,若 n 能被 i 整除则 i 是因数,输出 i。如 n=12 输出 1,2,3,4,6,12。
输入 个正整数 (),想找出它所有相邻的因数对,如,输入 ,因数对有 、、。下面哪段代码找不到所有的因数对?( )。
B:i 从 2 开始,遗漏相邻因数对 (1,2)。A/C/D 都能找到 (1,2)(C 通过 i=2 输出 (1,2),D 通过 i=1 输出 (1,2))。
质数的判定和筛法的目的并不相同,质数判定旨在判断特定的正整数是否为质数,而质数筛法意在筛选出范围内的所有质数。
对。质数判定只回答单个 N 是否为质数,试除到 sqrt(N) 即可;质数筛法(如埃氏筛)一次性筛出区间内全部质数,二者目的与输出规模都不同。
素数的线性筛法时间复杂度为( )。
A:线性筛(欧拉筛)用最小质因子标记每个合数,保证每个合数只被筛一次,每个数至多处理常数次,总复杂度为 O(n),优于埃氏筛的 O(n log log n)。
唯一分解定理描述了关于正整数的什么性质?
B:唯一分解定理指任何大于 1 的整数都能唯一分解为质数乘积。A 是哥德巴赫猜想;C 应写成 gcd×lcm=a×b;D 中 2 是偶质数,均不构成该定理。
干支纪年法是中国传统的纪年方法,由 个天干和 个地支组合成 个天干地支。由公历年份可以根据以下公式和表格换算出对应的天干地支。
天干=(公历年份)除以 所得余数
地支=(公历年份)除以 所得余数
例如,今年是 年, 除以 余数为 ,查表为“庚”; 除以 ,余数为 ,查表为“子”,所以今年是庚子年。
请问 年的天干地支是( )。
C:己丑。按干支纪年(公历-4)mod 10/12 取天干地支:1949-4=1945,mod 10=5 → 己(甲乙丙丁戊己庚辛壬癸),mod 12=1 → 丑(子丑寅卯辰巳午未申酉戌亥),故 1949 年为己丑年。
小杨想写一个程序来算出正整数 N 有多少个因数,经过思考他写出了一个重复没有超过 N/2 次的循环就能够算出来了。
对。因数成对出现,枚举 1 到 N/2 检查 N%i==0 计数,再加上 N 自身,即可求出全部因数个数,循环次数恰好不超过 N/2。
找出自然数 以内的所有质数,常用算法有埃氏筛法和线性筛法,其中埃氏筛法效率更高。
错。埃氏筛每个合数可能被多个质因子重复标记,复杂度 O(nloglogn);线性筛每个合数只被最小质因子筛一次,复杂度 O(n),线性筛效率更高。
素数表的埃氏筛法和线性筛法的时间复杂度都是 。
错。埃氏筛的时间复杂度是 O(N log log N),而线性筛(欧拉筛)保证每个合数只被其最小质因子筛一次,总复杂度为 O(N),两者并不相同。
在求解所有不大于 的素数时,线性筛法(欧拉筛)都应当优先于埃氏筛法使用,因为线性筛法的时间复杂度为 ,低于埃氏筛法的 。
错。线性筛理论 O(n) 虽优于埃氏筛 O(n log log n),但埃氏筛实现简单、常数小,n 不大时实际更快更常用,故不能断言任何情况都应优先采用线性筛。
下面的代码用于判断整数 是否是质数,错误的说法是( )。
01bool is_prime(int n) { 02 if (n <= 1) return false; 03 04 int finish_number = static_cast<int>(sqrt(n)) + 1; 05 for (int i = 2; i < finish_number; ++i) { 06 if (n % i == 0) 07 return false; 08 } 09 return true; 10}
D:线性筛 O(n) 优于埃氏筛 O(nloglogn),说埃氏筛效率最高错误。该代码只判单个数、试除到 sqrt(n);若要连续筛出质数,埃氏筛、线性筛确实更快,A、B、C 均正确。
关于埃氏筛和线性筛的比较,下列说法错误的是( )。
B:线性筛理论 O(n) 确比埃氏筛 O(nloglogn) 优,但 n≤10^7 的常见范围内埃氏筛实现简单、常数小,实测往往更快,故 B 的结论错误,D 正确。
埃氏筛中将内层循环从 j = i*i 开始而不是 j = 2*i 的主要原因是( )。
01vector<int> eratosthenes_sieve(int n) { 02 vector<bool> is_composite(n + 1, false); 03 vector<int> primes; 04 for (int i = 2; i <= n; i++) { 05 if (is_composite[i]) continue; 06 primes.push_back(i); 07 for (long long j = (long long)i * i; j <= n; j += i) 08 is_composite[j] = true; 09 } 10 return primes; 11}
C:小于 i² 的 i 的倍数 k·i 中 k<i,其必含小于 i 的质因子,早在以该质因子为外层 i 时已被标记,故从 i² 开始可免重复标记;A、B 说法错误,且优化后仍是 O(n log log n) 而非 O(n)。
下面关于埃氏筛法的说法正确的是( )。
B:埃氏筛从每个素数出发,把它的 2 倍、3 倍等倍数标记为合数,剩余未标记的即素数;A 错,同一合数会被多个质因子重复标记,这正是它与线性筛的区别。
下述代码实现素数表的埃拉托斯特尼筛法,筛选出所有小于等于 n 的素数,则横线上应填的最佳代码是( )。
01void sieve_Eratosthenes(int n) { 02 vector<bool> is_prime(n + 1, true); 03 vector<int> primes; 04 05 for (int i = 2; i * i <= n; i++) { 06 if (is_prime[i]) { 07 primes.push_back(i); 08 ____________ { // 在此处填入代码 09 is_prime[j] = false; 10 } 11 } 12 } 13 14 for (int i = sqrt(n) + 1; i <= n; i++) { 15 if (is_prime[i]) { 16 primes.push_back(i); 17 } 18 } 19 20 return primes; 21}
C:j 从 i×i 开始、以 i 为步长把 i 的倍数标 false;从 i×i 起因为 2i 到 (i−1)i 已被更小的质因子筛过,步长 i 保证只访问倍数;A、B 步长为 1 会误标大量数。
下述代码实现素数表的线性筛法,筛选出所有小于等于 n 的素数,则横线上应填的代码是( )。
01vector<int> sieve_linear(int n) { 02 vector<bool> is_prime(n + 1, true); 03 vector<int> primes; 04 05 for (int i = 2; i <= n / 2; i++) { 06 if (is_prime[i]) 07 primes.push_back(i); 08 ____________ { // 在此处填入代码 09 is_prime[i * primes[j]] = 0; 10 if (i % primes[j] == 0) 11 break; 12 } 13 } 14 15 for (int i = n / 2 + 1; i <= n; i++) { 16 if (is_prime[i]) 17 primes.push_back(i); 18 } 19 20 return primes; 21}
A:j 从 0 开始遍历 primes,用 i×primes[j] 标记合数,并限制 i×primes[j]≤n;一旦 i 能被 primes[j] 整除就 break,保证每个合数只被最小质因数筛一次;B 误用 i×j,C 漏掉 primes[0]。
下述代码实现素数表的埃拉托色尼(埃氏)筛法,筛选出所有小于等于 的素数。下面说法正确的是( )。
01vector<int> sieve_Eratosthenes(int n) { 02 vector<bool> is_prime(n + 1, true); 03 vector<int> primes; 04 05 for (int i = 2; i * i <= n; i++) { 06 if (is_prime[i]) { 07 primes.push_back(i); 08 09 for (int j = i * i; j <= n; j += i) { 10 is_prime[j] = false; 11 } 12 } 13 } 14 15 for (int i = sqrt(n) + 1; i <= n; i++) { 16 if (is_prime[i]) { 17 primes.push_back(i); 18 } 19 } 20 21 return primes; 22}
B:从 j=ii 开始标记,i 的倍数中小于 ii 的已被更小质因子标过,避免重复标记;整体复杂度 O(n log log n),且 sieve_Eratosthenes(10) 返回 2、3、5、7,不含 9。
下述代码实现素数表的线性筛法,筛选出所有小于等于 的素数。下面说法正确的是( )。
01vector<int> sieve_linear(int n) { 02 vector<bool> is_prime(n + 1, true); 03 vector<int> primes; 04 05 for (int i = 2; i <= n/2; i++) { 06 if (is_prime[i]) 07 primes.push_back(i); 08 09 for (int j = 0; j < primes.size() && i * primes[j] <= n; j++) { 10 is_prime[ i * primes[j] ] = 0; 11 if (i % primes[j] == 0) 12 break; 13 } 14 } 15 16 for (int i = n/2 +1; i <= n; i++) { 17 if (is_prime[i]) 18 primes.push_back(i); 19 } 20 21 return primes; 22}
A:线性筛每个合数只被其最小质因数标记一次,整体时间复杂度为 O(n);B 错在合数并非被所有质因子各标记一次,否则无法保证线性。
下述代码实现素数表的线性筛法,筛选出所有小于等于 n 的素数,横线上应填的最佳代码是( )。
01vector<int> sieve_linear(int n) { 02 vector<bool> is_prime(n + 1, true); 03 vector<int> primes; 04 if (n < 2) return primes; 05 is_prime[0] = is_prime[1] = false; 06 for (int i = 2; i <= n / 2; i++) { 07 if (is_prime[i]) 08 primes.push_back(i); 09 for (int j = 0; ____________ ; j++) { // 在此处填入代码 10 is_prime[i * primes[j]] = false; 11 if (i % primes[j] == 0) 12 break; 13 } 14 } 15 for (int i = n / 2 + 1; i <= n; i++) { 16 if (is_prime[i]) 17 primes.push_back(i); 18 } 19 return primes; 20}
C:内层循环既要保证 j 不越出 primes 数组(j<primes.size()),又要保证 i*primes[j]<=n 使 is_prime 下标不越界,两条件缺一不可;A、B 各自只满足其一仍可能越界,D 的 j<=n 完全错误。
如下为线性筛法,用于高效生成素数表,其核心思想是每个合数只被它的最小质因数筛掉一次,时间复杂度为 。
01vector<int> linearSieve(int n) { 02 vector<bool> is_prime(n + 1, true); 03 vector<int> primes; 04 05 for (int i = 2; i <= n; ++i) { 06 if (is_prime[i]) { 07 primes.push_back(i); 08 } 09 10 for (int j = 0; j < primes.size() && i * primes[j] <= n; ++j) { 11 is_prime[i * primes[j]] = false; 12 if (i % primes[j] == 0) { 13 break; 14 } 15 } 16 } 17 return primes; 18}
对。内层循环在 i%primes[j]==0 时立即 break,保证每个合数只被其最小质因数 primes[j] 筛一次,外层共 n 轮,时间复杂度为 O(n)。
函数 sieve 实现埃拉托斯特尼筛法(埃氏筛),横线处应填入( )。
01vector<bool> sieve(int n) { 02 vector<bool> is_prime(n+1, true); 03 is_prime[0] = is_prime[1] = false; 04 for(int i = 2; i <= n; i++) { 05 if(is_prime[i]) { 06 for(int j = ____________; j <= n; j += i) { 07 is_prime[j] = false; 08 } 09 } 10 } 11 return is_prime; 12}
D:内层从 ii 开始筛,因小于 i² 的合数必含更小质因子、已被筛掉;从 i 开始会把素数自身标成合数,从 i+1、i2 开始则要么漏筛要么多筛。
函数 linearSieve 实现线性筛法(欧拉筛),横线处应填入( )。
01vector<int> linearSieve(int n) { 02 vector<bool> is_prime(n+1, true); 03 vector<int> primes; 04 for(int i = 2; i <= n; i++) { 05 if(is_prime[i]) primes.push_back(i); 06 for(int p : primes) { 07 if(p * i > n) break; 08 is_prime[p * i] = false; 09 if(____________) break; 10 } 11 } 12 return primes; 13}
A:欧拉筛用 primes 中的质数 p 标记 i 的倍数,当 i%p==0 时 p 已是 i 的最小质因子,继续用更大质数 q 标记的 iq 也必被 p 标记,故 break。
线性筛关键是“每个合数只会被最小质因子筛到一次”,因此为 。
对。线性筛中当 i%p==0 即 break,此时 p 是 i 的最小质因子,保证每个合数只被其最小质因子标记一次,标记总次数与 n 同阶,故复杂度为 O(n)。
下面代码实现了欧拉(线性)筛,横线处应填写( )。
01vector<int> euler_sieve(int n) { 02 vector<bool> is_composite(n + 1, false); 03 vector<int> primes; 04 for (int i = 2; i <= n; i++) { 05 if (!is_composite[i]) 06 primes.push_back(i); 07 for (int j = 0; ____________ && (long long)i * primes[j] <= n; j++) { 08 is_composite[i * primes[j]] = true; 09 if (i % primes[j] == 0) 10 break; 11 } 12 } 13 return primes; 14}
C:内层循环需枚举已筛出的全部质数,越界条件应为 j<primes.size();A、B 用 n 或 sqrt(n) 与下标无关,D 用 j<i 在质数个数不足 i 时访问 primes[j] 越界。
线性筛相比埃氏筛的核心改进在于:埃氏筛中一个合数可能被多个质数重复标记,线性筛通过"每个合数只被其最大质因子筛去"的策略,保证每个合数恰好被标记一次,从而实现 的时间复杂度。
错。线性筛的关键是每个合数只被其最小质因子筛去:内层当 i%primes[j]==0 即 break,防止更大质数重复标记;题述最大质因子与线性筛的策略相反。
假设函数 gcd() 函数能正确求两个正整数的最大公约数,则下面的 lcm(a, b) 函数能正确找到两个正整数 和 的最小公倍数。
01int lcm(int a, int b) { 02 return a / gcd(a, b) * b; 03}
对。最小公倍数公式 lcm=a×b÷gcd(a,b),先算 a/gcd(a,b) 得整数再乘 b,结果正确且避免 a×b 先溢出;当 gcd=1 时 lcm=a×b 也成立。
线性筛法与埃氏筛法相比的优势是( )。
C:更快速。线性筛让每个合数只被其最小质因子筛掉一次,复杂度 O(n),比埃氏筛 O(n log log n) 更快;它实现更复杂,内存相当,准确性无差别。
埃氏筛法和欧拉筛法都是使用筛法思想生成素数表的算法,欧拉筛法的时间复杂度更低。( )
对。埃氏筛复杂度 O(n log log n),欧拉筛(线性筛)每个合数只被最小质因子筛一次,复杂度 O(n),更低,故说法正确,故对。
下⾯关于“唯⼀分解定理”和“素数筛法”的说法中,错误的是( )。
D:埃氏筛 O(n log log n) 源于调和级数式标记次数,与唯一分解定理无直接因果,D 说法错误;A、B、C 均正确,故选 D。
下面 init_sieve 函数的时间复杂度为( )。
01int sieve[MAX_N]; 02void init_sieve(int n) { 03 for (int i = 1; i <= n; i++) 04 sieve[i] = i; 05 for (int i = 2; i <= n; i++) 06 for (int j = i; j <= n; j += i) 07 sieve[j]--; 08}
B:内层循环 j 以 i 为步长,总执行次数 n/2+n/3+…+n/n≈n·ln n,即调和级数,复杂度 O(n log n),故选 B。
下面程序的时间复杂度为( )。
01int primes[MAXP], num = 0; 02bool isPrime[MAXN] = {false}; 03void sieve() { 04 for (int n = 2; n <= MAXN; n++) { 05 if (!isPrime[n]) 06 primes[num++] = n; 07 for (int i = 0; i < num && n * primes[i] <= MAXN; i++) { 08 isPrime[n * primes[i]] = true; 09 if (n % primes[i] == 0) 10 break; 11 } 12 } 13}
A:这是欧拉线性筛,每个合数只被其最小质因子筛掉一次,内层循环总次数为 O(n),故整体时间复杂度为 O(n),故选 A。故 A 正确。
下⾯程序的时间复杂度为( )。
01bool notPrime[N] = {false}; 02void sieve() { 03 for (int n = 2; n * n < N; n++) 04 if (!notPrime[n]) 05 for (int i = n * n; i < N; i += n) 06 notPrime[i] = true; 07}
C:O(N loglog N)。埃氏筛外层只到 √N,内层从 n² 起以步长 n 标记倍数;每个质数 p 标记约 N/p 个数,总量约为 N∑1/p≈N·loglog N。
下面的欧氏筛法程序中,两个横线处应填入的分别是 ( )
01bool isPrime[MAXN + 1] = {false}; 02int primes[MAXP], num = 0; 03void sieve() { 04 for (int n = 2; n <= MAXN; n++) { 05 if (!isPrime[n]) primes[num++] = n; 06 for (int i = 0; i < num && (此处1); i++) { 07 if (此处2) 08 break; 09 } 10 } 11}
C:第一个空 nprimes[i]<=MAXN 保证筛到的合数不越界;第二个空 n%primes[i]==0 时 break——n 的最小质因子是 primes[i],则 nprimes[i+1] 应由更小的质因子筛掉,提前终止保证线性。
下列程序实现了线性筛法(欧拉筛),用于在 时间内求出 之间的所有质数。为了保证每个合数只被其最小质因子筛掉,横线处应填入的语句是( )。
01for (int i = 2; i <= n; i++) { 02 if (!not_prime[i]) primes[++cnt] = i; 03 for (int j = 1; j <= cnt && i * primes[j] <= n; j++) { 04 not_prime[i * primes[j]] = true; 05 if (________) break; // 在此处填入选项 06 } 07}
C:i%primes[j]==0。当 primes[j] 是 i 的最小质因子时 break,保证更大的 primes[j+1]·i 会由更小的质因子在后续被筛掉,每个合数只筛一次。
下列线性筛的代码片段中,当枚举到质数 且 i % p == 0 时,使用 break 停止继续枚举。这样做的目的是( )。
01for (int i = 2; i <= n; ++i) { 02 if (!is_composite[i]) 03 primes.push_back(i); 04 for (int p : primes) { 05 if (i * p > n) 06 break; 07 is_composite[i * p] = true; 08 if (i % p == 0) 09 break; 10 } 11}
B:i%p==0 时 p 已是 i 的最小质因子,继续乘更大的质数得到的合数会由更小的质因子在别处筛掉,break 避免重复标记,保证每个合数只被其最小质因子筛一次。