特别基础的数论

本文主要讲了线性筛素数、分解质因数算法。

线性筛素数

P3383 【模板】线性筛素数

这里只讲欧拉筛

算法思路:若是枚举到一个数x,如果它没被标记成合数,那么加入素数数组,同时再用一个循环把所有小于x最小质因子的质数乘以x的数标记成合数。这样是有线性复杂度的。

既然是线性的正确算法,那应该能保证没漏筛、没重复筛。

证明:

设合数 x 有两个质因子 a,b(a<b)

s 可以表示成 s=a×sa=b×sb

可以得到 sb<sa<s

那么我们就可以用 s 最小的质因子来筛掉 s,就只会筛一次。

不妨设 a 就是最小的质因子,那么 sa 的最小的质因子一定大于等于 a,那么欧拉筛就一定在枚举到 sa 能筛掉 s

但是在枚举到 sb 时,因为它的最小的质因子一定大于 a,那么欧拉筛就不会筛到 s

综上所述,s 当且仅当枚举到 sa 时会被筛,所以就不会重复筛也不会漏筛。

代码:

#include <bits/stdc++.h>
using namespace std;
const int MAXN=1e8+100;
bool isp[MAXN];
int prime[MAXN>>4],pcnt;
void init(int n) {
	for(int i=2; i<=n; ++i) {
		if(!isp[i])prime[++pcnt]=i;
		for(int j=1,x; j<=pcnt&&(x=prime[j]*i)<=n; ++j) {
			isp[prime[j]*i]=1;
			if(!(i%prime[j]))break;
		}
	}
}
int main() {
	int n,q;
	scanf("%d%d",&n,&q);
	init(n);
	for(int i=1,x; i<=q; ++i) {
		scanf("%d",&x);
		printf("%d\n",prime[x]);
	}
	return 0;
}

分解质因数

这个可以做到O(n)n分解

可以发现,大于n的质因数最多有一个,且指数一定为1

不然它们乘起来就大过n了,所以我们可以只枚举n的质因数。

先放代码

#include<bits/stdc++.h>
using namespace std;
const int MAXN=40;
int p[MAXN],c[MAXN],pcnt,n;
void work(int n) {
	for(int i=2; i*i<=n; ++i) {
		if(!(n%i)) {//枚举到一个质因数
			p[++pcnt]=i;//存下
			while(!(n%i)) {//计算指数
				n/=i;
				++c[pcnt];
			}
		}//由于比这个因子更小的质因子都被除掉了
      //所以这个因数一定是质因数
	}
	if(n>1) {//有大于根号n的质因数
		p[++pcnt]=n;//存下
		c[pcnt]=1;
	}
}
int main() {
	scanf("%d",&n);
	work(n);
	for(int i=1; i<=pcnt; ++i) {
		printf("%d %d\n",p[i],c[i]);
	}
	return 0;
}
posted @   mod998244353  阅读(60)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
Live2D
欢迎阅读『特别基础的数论』
点击右上角即可分享
微信分享提示