质因子分解表+欧拉筛+埃式筛

模版

质因子分解表

//质因子分解表:线形筛➕最小质因子🟰质因子分解表
void init() {
    vector<int>prime; //质数数组
    for (int i = 2; i <= N; i++) {
        if(!a[i]) { //是质数
            a[i] = i; //只有自己一个因子
            prime.push_back(i);
        }
        for (auto p: prime) {
            if(i*p > N) break; 
            a[i*p] = p; //a数组储存i的最小质数因子
            if(i % p == 0) break; //已经找到最小因子,剩下的交给后面再找
        }
    }
}

vector<int> cal(int x) {
    vector<int>op;
    while(x > 1) {
        int p = a[x];
        op.push_back(p);
        while(x % p == 0) x/=p;
        //依次找到x的每一个最小质数因子
    }return op;
}//x的所有质因子

欧拉筛

void init()
{
    int cnt = 0;
    for (int i = 1; i <= 1000000; i++)  a[i] = 1;
    a[1] = 0;
    for (int i = 2; i <= 1000000; i++)
    {
            if(a[i]==1)b[++cnt] = i;
            for (int j = 1; j <= cnt; j++)
            {
                if (i * b[j] > 1000000)break;
                a[i * b[j]] = 0; //判断这个数不是质数
                if (!(i % b[j]))break; //剩下的数字交给后面判断
            }
        
    }
}

埃式筛

const int N=1e5;
int a[N]; int b[N];
void init()
{
    int cnt = 0;
    for (int i = 2; i <= N; i++)
    {
        if (a[i] == 0) {
            b[cnt++] = i; //是素数
            for (int j = 2; j <= N; j++)
            {
                if (i * j > N) break;
                a[i * j] = 1; //不是素数
            }
        }
    }
    for (int i = 0; i < cnt; i++) cout << b[i] << ' ';
}

例题

<1>(萤火虫难题)

题解:
在这里插入图片描述

代码:

#include<iostream>
#include<set>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<string>
#include<string.h>
#include<map>
#include<math.h>

using namespace std;

const int N = 5e5+10;
int n; int c[N];
int w[N];
int cnt = 0;
int a[N],b[N];

//质因子分解表:线形筛➕最小质因子🟰质因子分解表
void init() {
   vector<int>prime;
   for (int i = 2; i <= N; i++) {
       if(!a[i]) {
           a[i] = i;
           prime.push_back(i);
       }
       for (auto p: prime) {
           if(i*p > N) break;
           a[i*p] = p;
           if(i % p == 0) break;
       }
   }
}

struct ty{
   int len;//以数字i结尾的满足条件的最长串
   int col;//数字i的颜色
}r1[N],r2[N];//维护最优和次优的颜色情况

vector<int> cal(int x) {
   vector<int>op;
   while(x > 1) {
       int p = a[x];
       op.push_back(p);
       while(x % p == 0) x/=p;
   }return op;
}//x的所有质因子

signed main() {
   cin >> n; init();
   for (int i = 1; i <= N-5; i++) {
       r1[i] = {0,0};
       r2[i] = {0,0};
   }int ans = 1;

   for (int i = 1; i <= n; i++) {
       cin >> w[i];  //亮度不互质
   }for (int i = 1; i <= n; i++) {
       cin >> c[i];  //颜色不相等
   }

   for (int i = 1; i <= n; i++) {
       auto fs = cal(w[i]);
       int res = 0;

       for (auto p: fs) {
           if(c[i] != r1[p].col) res = max(res,r1[p].len+1);
           else res = max(res,r2[p].len+1);
       }

       ans = max(ans,res);

       for (auto p: fs) {
           if(c[i] == r1[p].col) r1[p].len = max(r1[p].len,res);
           else {
               if(res > r1[p].len) {
                   r2[p].len = r1[p].len;
                   r2[p].col = r1[p].col;
                   r1[p].len = res;
                   r1[p].col = c[i];
               }else if(res > r2[p].len){
                   r2[p].len = res;
                   r2[p].col = c[i];
               }else if(res == r2[p].len) {
                   r2[p].col = 0;
               }
           }
       }
   }cout << ans << endl;
}

### 关于欧拉法的Java代码实现及其解释 #### 欧拉法简介 欧拉法(也称为线性),是对传统埃拉托斯特尼法的一种改进,能够在O(n)的时间复杂度下找出小于等于给定整数n的所有素数。该方法通过标记合数并记录最小质因子的方式实现了高效的选过程。 #### Java代码实现 以下是基于上述描述编写的Java版本欧拉法的具体实现: ```java import java.util.Scanner; public class EulerSieve { public static void main(String[] args){ Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); // 初始化数组 boolean[] isPrime = new boolean[n + 1]; for (int i = 0; i <= n; ++i) { isPrime[i] = true; } isPrime[0] = false; isPrime[1] = false; int[] primes = new int[n / 2]; // 存储找到的素数 int pCount = 0; // 记录已发现素数的数量 for (int num = 2; num <= n; ++num) { if (isPrime[num]) { primes[pCount++] = num; } for (int j = 0; j < pCount && num * primes[j] <= n; ++j) { isPrime[num * primes[j]] = false; if (num % primes[j] == 0) break; } } // 输出所有素数 for (int k = 0; k < pCount; ++k) { System.out.print(primes[k] + " "); } } } ``` 这段程序首先读取用户输入的最大范围`n`,接着初始化布尔类型的辅助数组`isPrime[]`用于判断某个数值是否为素数,并设置初始状态为全部视为可能的素数[^1]。随后遍历每一个自然数,在确认其未被标记为非素数的情况下将其加入到素数列表中;同时利用已经获得的小素数去更新后续更大数字的状态直至达到边界条件为止。特别注意当遇到当前考察对象能够整除任一已有小素数时立即停止进一步操作以避免重复计算不必要的组合形式[^2]。 #### 设计思路与优势分析 相比于经典的埃氏欧拉的核心在于只让每个合数由它最小的那个因数负责删除一次,从而使得整个算法效率更高更稳定。具体来说就是每当新发现了某一个素数p之后,就立刻用这个新的素数去除掉后面所有的倍数位置上的候选者们——但是这里有一个重要的剪枝策略:一旦发现正在处理的目标值可以被现有的任意一个小素数q整除,则不再继续尝试更大的素数r作为乘积因子,因为此时pq已经是目标值的一个合法分解方案了。 这种做法不仅减少了无谓的操作次数,而且保证了最终得到的结果集里不会存在任何多余的冗余项,因此非常适合用来应对大规模数据量下的高效求解场景需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值