首页 > 其他分享 >【模板】筛法

【模板】筛法

时间:2022-10-07 15:23:35浏览次数:55  
标签:prime const 筛法 int mu minprime 模板 size

\(prime\)

const int N = 1e7+10;
int prime[N];
bool notprime[N];
int minprime[N];
void prime_sieve(const int maxn) {
	register int i, multi_helper;
	register int* j;
	const int half_maxn = maxn>>1;
	for(i = 2;i <= half_maxn;++i) {
		if(!notprime[i]) {
			prime[++prime[0]] = i;
			minprime[i] = i;
		}
		for(j = prime+1;*j&&*j <= minprime[i];++j) {
			notprime[i*(*j)] = true;
			minprime[i*(*j)] = *j;
		}
	}
	for(;i <= maxn;++i) 
		if(!notprime[i]) {
			prime[++prime[0]] = i;
			minprime[i] = i;
		}
}
const int N = 1e8+5e7+10;
const int P = 1e7+10;
int prime[P];
int minprime[N];
void prime_sieve(const int maxn) {
	register int i, upd;
	register int* j;
	const int half_maxn = maxn>>1;
	for(i = 2;i <= half_maxn;++i) {
		if(!minprime[i]) {
			prime[++prime[0]] = i;
			minprime[i] = i;
		}
		upd = std :: min(maxn/i,minprime[i]);
		for(j = prime+1;*j&&*j <= upd;++j) 
			minprime[i*(*j)] = *j;
	}
	for(;i <= maxn;++i) 
		if(!minprime[i]) 
			prime[++prime[0]] = i;
}

这个常数还是比较小的。

可以在 \(80\ ms\) 内处理出 \(1e7\) 以内的素数。

可以在 \(0.8\ s\) 内处理出 \(1e8\) 以内的素数。

\(upd\ on\ 2022.10.07\)

const int N = 100000005;
const int P = 30000005;
int prime[P];
int *p = prime;
int minprime[N];
void tree_line(int max_size) {
	const int half_size = max_size>>1;
	const int tree_size = max_size/3;
	const int sqrt_size = sqrt(max_size);
	int i, upd;
	int *j;
	minprime[2] = minprime[4] = *++p = 2;
	for(i = 3;i <= sqrt_size;++i) {
		if(!minprime[i]) 
			*++p = minprime[i] = i;
		for(j = prime+1;;++j) {
			minprime[i*(*j)] = *j;
			if(*j == minprime[i]) 
				break;
		}
		++i;
		minprime[i<<1] = 2;
	}
	for(;i <= tree_size;++i) {
		if(!minprime[i]) 
			*++p = minprime[i] = i;
		if((upd = max_size/i) >= minprime[i]) {
			for(j = prime+1;*j <= minprime[i];++j) {
				minprime[i*(*j)] = *j;
				if(j == p) 
					break;
			}
		} else {
			for(j = prime+1;*j <= upd;++j) {
				minprime[i*(*j)] = *j;
				if(j == p) 
					break;
			}
		}
		++i;
		minprime[i<<1] = 2;
	}
	for(;i <= half_size;++i) {
		if(!minprime[i]) 
			*++p = minprime[i] = i;
		minprime[i<<1] = 2;
		++i;
		minprime[i<<1] = 2;
	}
	for(;i <= max_size;i += 2) 
		if(!minprime[i]) 
			*++p = i;
}

这份板子在电脑稳定情况下,筛 \(1e8\) 仅需 \(465\,ms\) 左右。(-O2)

其中加入了对:

  1. \(\sqrt n\) 的讨论

  2. \(\frac{n}{3}\) 的讨论

  3. \(\frac{n}{2}\) 的讨论

  4. 奇偶性的讨论

下一步准备搞数论分块,降低除法次数。

\(\varphi(n)\)

ull phi[z];
void line_phi(int n) {
	b.reset();
	phi[1] = 1;
	for(int i = 2;i <= n;++i) {
		if(!b[i]) {
			prime[++prime[0]] = i;
			phi[i] = i-1;
		}
		for(int j = 1;j <= prime[0];++j) {
			if(i*prime[j] > n) break;
			if(i%prime[j]) 
				phi[i*prime[j]] = phi[i]*phi[prime[j]];
			else {
				phi[i*prime[j]] = phi[i]*prime[j];
				break;
			}
		}
	}
}

\(\mu(n)\)

int mu[z];
void line_mu(int n) {
	b.reset();
	mu[1] = 1;
	for(int i = 2;i <= n;++i) {
		if(!b[i]) {
			mu[i] = -1;
			prime[++prime[0]] = i;
		}
		for(int j = 1;j <= prime[0];++j) {
			if(i*j > n) break;
			b[i*prime[j]] = 1;
			if(i%prime[j] == 0) {
				mu[i*prime[j]] = 0;
				break;
			}
			mu[i*prime[j]] = -mu[i];
		}
	}
}

开始卡常。

const int N = 1e7+10;
const int P = 4e6+10;
int mu[N];
int minprime[N];
int prime[N];
void init(int init_size) {
	const int half_size = init_size>>1;
	register int i, *j, upd, m_h;
	register int *p = prime+1;
	mu[1] = 1;
	for(i = 2;i <= half_size;++i) {
		if(!minprime[i]) {
			minprime[i] = i;
			*p++ = i;
			mu[i] = -1;
		}
		if((upd = init_size/i) >= minprime[i]) {
			for(j = prime+1;*j < minprime[i];++j) {
				minprime[m_h = i*(*j)] = *j;
				mu[m_h] = -mu[i];
			}
			minprime[m_h = i*(*j)] = *j;
			mu[m_h] = 0;
		} else {
			for(j = prime+1;*j <= upd;++j) {
				minprime[m_h = i*(*j)] = *j;
				mu[m_h] = -mu[i];
			}
		}
		mu[i] += mu[i-1];
	}
	for(;i <= init_size;++i) 
		if(!minprime[i]) 
			mu[i] = mu[i-1]-1;
		else 
			mu[i] += mu[i-1];
}

可以稳定在 \(128\,ms\) 左右,不错了。

注意卡常的板子筛的是 \(mu(n)\) 的前缀和。

\(\tau(n)\)

ull tau[z];
ull num[z];
void line_tau(int n) {
	tau[1] = 1;
	for(int i = 2;i <= n;++i) {
		if(!b[i]) {
			b[i] = 1;
			prime[++prime[0]] = i;
			tau[i] = 2;
			num[i] = 1;
		}
		for(int j = 1;j <= prime[0];++j) {
			if(i*prime[j] > n) break;
			b[i*prime[j]] = 1;
			if(i%prime[j] == 0) {
				num[i*prime[j]] = num[i]+1;
				tau[i*prime[j]] = tau[i]/num[i*prime[j]]*(num[i*prime[j]]+1);
				break;
			} else {
				num[i*prime[j]] = 1;
				tau[i*prime[j]] = tau[i]*2;
			}
		}
	}
}

\(\sigma(n)\)

ull sigma[z];
ull g[z];
void line_sigma(int n) {
	sigma[1] = g[1] = 1;
	for(int i = 2;i <= n;++i) {
		if(!b[i]) {
			b[i] = 1;
			prime[++prime[0]] = i;
			g[i] = i+1;
			sigma[i] = i+1;
		}
		for(int j = 1;j <= prime[0];++i) {
			if(i*prime[j] > n) break;
			b[i*prime[j]] = 1;
			if(i%prime[j] == 0) {
				g[i*prime[j]] = g[i]*prime[j]+1;
				sigma[i*prime[j]] = sigma[i]/g[i]*g[i*prime[j]];
				break;
			} else {
				sigma[i*prime[j]] = sigma[i]*sigma[prime[j]];
				g[i*prime[j]] = 1+prime[j];
			}
		}
	}
}

标签:prime,const,筛法,int,mu,minprime,模板,size
From: https://www.cnblogs.com/bikuhiku/p/sieve_methods.html

相关文章

  • 微信小程序排行榜页面模板
    1需求在开发一款背单词的微信小程序时,为了加强用户的体验感,刺激用户积极学习,小程序中需要有排行榜的模块。通过打开天数来排名,让用户有攀比学习的心里。具体的页面截图如......
  • 模板基类与正确的派生类函数调用--Effective C++ Item 43
    问题描述假设我们有这样一个业务场景,我们管理着许多公司,每个公司都有一个自己的许多日志信息需要处理,于是为了方便,我们写了一个模板类用来处理这些公司的信息,并且将这些公......
  • 设计模式系列1 - 模板模式&策略模式
    分别讲述模板模式和策略模式的使用姿势,以及两者的区别,基于java。往期精选(欢迎转发~~)Java全套学习资料(14W字),耗时半年整理消息队列:从选型到原理,一文带你全部掌握肝了......
  • 我的CMakeLists.txt模板
    我的CMakeLists.txt模板,适用于windowsSDK风格的程序,不考虑测试和安装问题.rc资源文件部分,适用windows项目。#####################################################......
  • [答疑]需求说明书模板中的编写目的好象是废话
    ​​别把洋垃圾当宝贝-评InfoQ中国“敏捷……”文章(一)​​譯揮(25****466)10:00:20请教一个问题:在我们的需求说明书模板中,开头有一个编写目的要写。如何写比较有意义?如一......
  • P3834 【模板】可持久化线段树 2
    P3834主席树模板,求区间第k小。1#include<bits/stdc++.h>2usingnamespacestd;3#definelctr[i].ch[0]4#definerctr[i].ch[1]5#defineLctr[j].ch[0......
  • TZOJ 6948: 走迷宫/深搜模板
    描述 有一个迷宫,图案如图5.2.6所示,红色区域表示不能通行,蓝色区域表示能通行,在迷宫中通行的方向是上下左右四个方向。从入口(1,1)位置进入迷宫,编程判断能否从出口位置......
  • C++ 泛型(模板与容器)
    文章目录​​一、泛型的基本思想:​​​​函数模板的性质​​​​C++模版函数/类的语法​​​​类模板的性质​​​​二、C++STL简介​​​​2.1算法(algorithm)​​​​2.......
  • 高级vue 模板中 ref 的使用用法
    ref+普通dom标签 获取真实dom对象ref+组件标签 获取组件实例对象 <template>  <h1ref="h1Ref">www.96net.com.cn</h1>  <ref-comoonentref="co......
  • 字符串哈希 模板 例题
    字符串哈希可以快速判断两个子字符串是否相等原理:https://www.cnblogs.com/ydUESTC/p/15722400.html注意字符串哈希时后面的字符视为低位,这样方便取一段字符的哈希时先......