CSP-202312-2-因子化简
一、质数筛法
主流的质数筛法包括埃拉托斯特尼筛法(Sieve of Eratosthenes)、欧拉筛法(Sieve of Euler)、线性筛法(Linear Sieve)等。这些算法都用于高效地生成一定范围内的质数。
1. 埃拉托斯特尼筛法(Sieve of Eratosthenes):
- 从2开始,将2的倍数标记为合数,然后找到下一个未被标记的数,将其倍数标记为合数,重复这个过程,直到达到预定范围。
- 在每次标记过程中,未被标记的数即为质数。
const int MAX_SIZE = 1001;
int primes[MAX_SIZE]; // 存储素数的数组
void generatePrimes() {
bool isPrime[MAX_SIZE]; // 标记是否为素数
for (int i = 2; i < MAX_SIZE; i++) {
isPrime[i] = true; // 假设所有数字都是素数
}
// 从2开始,将2的倍数标记为合数
for (int i = 2; i * i < MAX_SIZE; i++) {
if (isPrime[i]) {
// 将 i 的倍数标记为非素数
for (int j = i * i; j < MAX_SIZE; j += i) {
isPrime[j] = false;
}
}
}
int count = 0; // 用于记录素数的个数
for (int i = 2; i < MAX_SIZE; i++) {
if (isPrime[i]) {
// 将素数存储在全局数组 primes 中
primes[count] = i;
count++;
}
}
}
2. 欧拉筛法(Sieve of Euler):
- 欧拉筛法是对埃拉托斯特尼筛法的改进,主要解决了合数被重复标记的问题。
- 对于每个数,只用最小质因子去标记,避免了重复标记。
- 通过对每个合数只标记一次,提高了效率。
3. 线性筛法(Linear Sieve):
- 线性筛法是对欧拉筛法的进一步改进,更加高效。
- 在筛质数的同时,顺便筛掉合数,每个合数都被最小质因子筛去。
- 使用一个额外的数组保存最小质因子,同时记录每个数的质因子个数。
- 线性筛法在遍历过程中只会被筛掉一次,避免了重复筛掉合数的问题。
二、解题思路
【核心思想】: 对输入的整数进行质因数分解,并保留出现次数不小于阈值
k
的素数部分,最后输出结果。
【注意】: 本题需要先通过质数筛法打印找出1000以内的质数,然后将其存为数组,直接调用generatePrimes()可能会时间超限
-
素数数组定义:
int primes[] = { 2, 3, 5, ... , 991, 997 };
,在数组中存储了一系列素数,用于后续的整数分解。 -
程序解释:
- 内层
for
循环遍历素数数组,对输入的整数n
进行素数分解。 - 内部的
while
循环统计每个素数的出现次数,如果次数不小于阈值k
,则将该素数的k次幂乘入最终结果ans
中。
- 内层
#include<iostream>
using namespace std;
int primes[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 507, 521, 523, 541, 547, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997 }; // 存储素数的数组
int main() {
int q;
cin >> q;
while (q--) {
long long n, k, ans = 1;
cin >> n >> k;
for (int i = 0; n > 1 && i < sizeof(primes) / sizeof(primes[0]); i++) {
int curK = 0; // curK记录当前素数的出现次数
// 统计每个素数对应的K
while (n % primes[i] == 0) {
curK++;
n /= primes[i];
}
// 不小于阈值的部分保留
if (curK >= k) {
for (int j = 0; j < curK; j++) {
ans *= primes[i];
}
}
}
cout << ans << endl; // 输出结果
}
return 0;
}
参考:CCFCSP202312-2因子化简 (质数筛法)C/C++ 满分