首页 > 其他分享 >[数论]素数筛和整数分块

[数论]素数筛和整数分块

时间:2023-06-17 09:11:05浏览次数:42  
标签:分块 数论 质数 pri long int 素数 include ll

Prime sieving and Integer blocking

一、Prime number sieve method

1.埃氏筛O(nloglogn)

从 2 开始,2是质数,那么2的倍数:4、6、8、10、12、14、16... 肯定不是质数
3是质数,那么3的倍数:6、9、12、15、18、21..... 肯定不是质数
4已经被筛去了(即被置为false),不是质数,那么4的倍数肯定被它的因子筛过,所以4不用看,跳过
... ...
没有被筛去的一定是质数,因为它没有被比它小的任何一个数筛去,说明它不是任何一个数的倍数,所以一定是质数。

#include <iostream>
using namespace std;
#include <cstring>      
 
const int N = 1e5;		
bool isPrime[N + 5];	
int primes[N + 5];		
int cnt = 0;	

void aiPrime()
{
	memset(isPrime,true,sizeof(isPrime));		
 
	for (int i = 2;i <= N / i;i++)//注意这里 i <= N / i就可以
	{
		if (isPrime[i])		//如果当前数是质数,那么将它的倍数都标记为 false
		{			
			for (int j = i * i; j <= N; j += i)
			{
				isPrime[j] = false;
			}
		}
	}
 
	for (int i = 2; i <= N; i++)		//将质数放入primes数组
	{
		if(isPrime[i])
			primes[cnt++] = i;
	}
}
 
int main()
{
	aiPrime();
	cout << cnt << endl;
	return 0;
}

2.线性筛

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn =1000010;
bool is_pri[maxn];
int pri[maxn];
int cnt;

void init(int n)
{
	memset(is_pri, true, sizeof(is_pri));
	is_pri[1] = false;
	cnt = 0;
	for (int i = 2; i <= n; i++)
	{
		if (is_pri[i])
			pri[++cnt] = i;
		for (int j = 1; j <= cnt && i * pri[j] <= n; j++)
		{
			is_pri[i * pri[j]] = false;
			if (i % pri[j] == 0)break;            
		}
	}
}

3.区间筛

给两个数字\(l,r\),求\(l~r\)中的所有素数\(p\)。
为了防止输出过大和防止打表,
给定\(a\),\(b\),输出这些素数\((a*p+b)\bmod 2^{32}\)的异或和。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned int u64;
const int N =10000100;
bool is_pri[N];
int pri[N/5];
int cnt;
ll l,r;
bool vis[N];
u64 ans = 0,a,b;
void init(int n)
{
	memset(is_pri, true, sizeof(is_pri));
	is_pri[1] = false;
	cnt = 0;
	for (int i = 2; i <= n; i++)
	{
		if (is_pri[i])
			pri[++cnt] = i;
		for (int j = 1; j <= cnt && i * pri[j] <= n; j++)
		{
			is_pri[i * pri[j]] = false;
			if (i % pri[j] == 0)break;            
		}
	}
}



int main()
{
	init(N);
	cin>>l>>r>>a>>b;
	for(int i = 1;i<=cnt;i++)
	{
		int p = pri[i];
		//cout<<p<<endl;
		//筛掉l~r里面p的倍数
		//从<=r的第一个p的倍数开始筛
		for(ll x = r/p*p;x>=l&&x>p;x-=p)
			vis[x-l] = 1;

	}
	
	for(ll i = max(2ll,l);i<=r;i++)
	{
		if(!vis[i-l])
		{
			ans = ans^(a*(u64)i+b);
		}
	}
	cout<<ans<<endl;
	return 0;
}

二、Integer_block

整数分块核心代码

for(ll l = 1;l<=n;l++)
{
	ll d = n/l,r = n/d;
	//l ... r这一段n/x都==d
	l = r;
}

eg1.\(\sum_{i = 1}^{n}(n \bmod i)\)

// 给定一个数字n,求∑(i=1~n)(n mod i)。
// 答案可能很大,输出对2^60取模的结果。
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long u64;
//n mod i = n-n/i*i
//对于l,r这一段,它的n/i都是d
//那这一段值等于n-d*i,是等差数列
u64 n,sum;

int main()
{
	cin>>n;
	for(u64 l = 1;l<=n;l++)
	{
		u64 d = n/l,r = n/d;
		sum += (n-l*d+n-r*d)*(r-l+1)/2;
		l = r;
	}
	cout<<sum%(1ull<<60)<<endl;
	return 0;
}

标签:分块,数论,质数,pri,long,int,素数,include,ll
From: https://www.cnblogs.com/nannandbk/p/17487024.html

相关文章

  • c# WebUploader 分块上传
    ​ASP.NET上传文件用FileUpLoad就可以,但是对文件夹的操作却不能用FileUpLoad来实现。下面这个示例便是使用ASP.NET来实现上传文件夹并对文件夹进行压缩以及解压。ASP.NET页面设计:TextBox和Button按钮。​编辑TextBox中需要自己受到输入文件夹的路径(包含文件夹),通过Button实......
  • .net WebUploader 分块上传
    ​ 一、概述 所谓断点续传,其实只是指下载,也就是要从文件已经下载的地方开始继续下载。在以前版本的HTTP协议是不支持断点的,HTTP/1.1开始就支持了。一般断点下载时才用到Range和Content-Range实体头。HTTP协议本身不支持断点上传,需要自己实现。 二、Range  用于请求头......
  • c#.net WebUploader 分块上传
    ​ 以ASP.NETCoreWebAPI 作后端 API ,用 Vue 构建前端页面,用 Axios 从前端访问后端 API,包括文件的上传和下载。 准备文件上传的API #region 文件上传  可以带参数        [HttpPost("upload")]        publicJsonResultuploadProject(I......
  • asp.net WebUploader 分块上传
    ​IE的自带下载功能中没有断点续传功能,要实现断点续传功能,需要用到HTTP协议中鲜为人知的几个响应头和请求头。 一. 两个必要响应头Accept-Ranges、ETag        客户端每次提交下载请求时,服务端都要添加这两个响应头,以保证客户端和服务端将此下载识别为可以断点续传......
  • (数论)判断素数(朴素,根号,埃氏筛,欧拉筛线性筛)
    //最基本求一个素数(on),(osqrt(n))#include<bits/stdc++.h>usingnamespacestd;intmain(){intn;cin>>n;for(inti=2;i<n;i++)//o(n)if(n%i==0){cout<<"no";return0;}for(i......
  • [数论]GCD&LCM&欧拉函——推柿子+例题
    GCD&LCM&欧拉函——推柿子一、\(\sum_{i=1}^{n}[\gcd(i,n)=d]\)\(\sum_{i=1}^{n}[\gcd(i,n)=d]\)\(=\sum_{i=1}^{\frac{n}{d}}[\gcd(i,\frac{n}{d})=1]\)\(=\phi(\frac{n}{d})\)二、\(\sum_{i=1}^{n}\gcd(i,n)\)\(\sum_{i=1}^{n}\gcd(i,......
  • Python多进程使用队列共享数据协同判断素数
    感谢江西师范大学李雪斌老师提供素材和第一版本代码。问题描述:创建两个队列,qIn用来存储指定范围内的整数,qOut用来存放该范围内的所有素数。创建多个进程,每个进程依次从qIn队列中获取整数,并判断是否为素数,如果是素数则存入qOut。技术要点:1)使用Python标准库multiprocessing创建和管理......
  • 查找一之顺序查找、二分查找、分块查找
    1、概念:在一些有序的或无序的数据元素中,通过一定的方法找出与给定关键字相同的数据元素的过程叫做查找,也就是给定一个值,在查找表中确定一个关键字等于给定值的记录或数据元素。2、平均查找长度(后期可能会增加)3、查找长度分为成功和失败两种4、顺序查找1、主要思想:将查找值......
  • 最优的素数判断代码(Python)是这样写出来的
    素数判断是个很经典的问题,各种语言的程序设计课程都会涉及到,按照素数定义(除了1和自身,素数没有其他因数)很容易写出下面的代码:defisPrime1(n):foriinrange(2,n):ifn%i==0:returnFalsereturnTrue功能完全没有问题,就是非常非常非常非常慢。......
  • Wireshark - HTTP Continuation——就是大包分块传输
    Wireshark-HTTPContinuationby JeremyCanfield |  Updated: March9th,2020  |  WiresharkarticlesLet'stakeanexamplewherethereisafilenamedStage1.phponthewww.example.comwebserver,andStage1.phpcontainsthephraseHelloWorld. When......