CSP-202312-2-因子化简(质数筛法)

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()可能会时间超限

  1. 素数数组定义: int primes[] = { 2, 3, 5, ... , 991, 997 };,在数组中存储了一系列素数,用于后续的整数分解。

  2. 程序解释:

    • 内层 for 循环遍历素数数组,对输入的整数 n 进行素数分解。
    • 内部的 while 循环统计每个素数的出现次数,如果次数不小于阈值 k,则将该素数的k次幂乘入最终结果 ans 中。
#include
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++ 满分

你可能感兴趣的:(c++,算法)