zoukankan      html  css  js  c++  java
  • 线性筛法

    线性筛法

    Eratosthenes 筛法利用的原理是 任意整数 x 的倍数 2x,3x,... 等都不是质数

    但是即便如此也会有重复标记的现象,例如12既会被2又会被3标记,在标记2的倍数时,(12 = 6*2),在标记3的倍数时,(12 = 4*3) ,根本原因是没有找到唯一产生12的方式。

    线性筛法的核心原理

    每个合数必有一个最大因子(不包括它本身),用这个因子把合数筛掉

    换言之:每个合数必有一个最小素因子,用这个因数把合数筛掉

    过程

    假设对于一个确定的整数 (i)(i) 是一个合数 (t) 的最大因数,(t) 显然可能不唯一(例如 30 和 45 最大因数都是 15)。但是仔细想一想,必然有一个p,满足:

    [t = i * p ~~ (ple i ,p是质数) ]

    • (p)为什么一定小于等于 (i)?因为 (i)(t) 的最大因数。
    • 为什么 (p) 一定是质数?因为如果 (p) 是合数,那么 (i) 就一定不是 (t) 的最大因数,因为 (p) 可以再拆成若干素数相乘,这些素数再与 (i) 相乘会使该因数更大。

    既然如此,我们只需要把所有小于 (i) 的质数 (p) 都挨个乘一次拿到所有合数就好了。可是,这样就不会有重复标记嘛?

    会的,我们一不小心就忘记了最初的条件。我们要满足 (i)(t) 的最大因数。如果 (p) 大于 (i) 的最小质因数,那 (i) 还是 (t) 的最大因数嘛?显然不是,任何一个合数 (t) 都能唯一分解为有限个质数的乘积,除去这其中最小的质因数,其他的都乘起来就是最大因数 (i) 。所以我们不能让 (p) 大于 (i) 的最小质因数(设为(x)),否则 (i) 将不再是 (t = i*p) 的最大因数,其最大因数应该是(i*p/x)

    下面有两个版本,核心处理稍有一点点不同,理解即可。

    版本一

    • v[i] 表示 i 的最小质因数。如果i就是质数,那么v[i] = i
    • prime[j] 表示第 j 个质数。与之前的筛法不同,这个数组是存放质数的,而不是标记质数的
    #define MAXN 1000012
    int prime[MAXN],v[MAXN];
    int m=0;//m表示现在筛出m个质数
    void primes(int n)
    {
    	for(int i=2;i<=n;i++)
        {
    		if(v[i]==0)//如果v[i]为0,说明 i 之前没有被筛到过,i 为质数
    		{
    			v[i] = i;
                 prime[++m] = i;
    		}
    		for(int j = 1;j<=m;j++)//遍历小于 i 的所有质数
    		{
                //如果质数大于 i 的最小质因数或者乘起来大于n就跳出循环
    			if(prime[j] > v[i] || prime[j] > n/i) break;
    			v[i*prime[j]] = prime[j];//标记 i*prime[j] 的最小质因数是prime[j]
    		}
    	}
    }
    

    版本二

    • v[i] i 为质数则为0,否则为 1
    • prime[j] 与上面相同
    #define MAXN 1000000
    int prime[MAXN],v[MAXN];
    int m=0;//m表示现在筛出m个质数
    void primes(int n)
    {
        v[1] = 1;//1不是质数,提前处理
    	for(int i=2;i<=n;i++)
        {
    		if(v[i]==0)//如果v[i]为0,说明 i 之前没有被筛到过,i 为质数
                 prime[++m] = i;
    		for(int j = 1;j<=m;j++)//遍历小于 i 的所有质数
    		{
                //乘起来大于就跳出循环
    			if(prime[j] > n/i) break;
    			v[i*prime[j]] = 1;//标记 i*prime[j] 的最小质因数是prime[j]
                 //当遇到最小的质数是i的因数时,break
                 if(i%prime[j]==0)break;
    		}
    	}
    }
    
  • 相关阅读:
    贝叶斯公式由浅入深大讲解—AI基础算法入门
    再谈前端HTML模板技术
    再谈angularJS数据绑定机制及背后原理—angularJS常见问题总结
    mac版chrome升级到Version 65.0.3325.18后无法打开百度bing搜狗
    图说js中的this——深入理解javascript中this指针
    web app响应式字体设置!rem之我见
    【2020-04-18】 加班
    【2020-04-06】汇郡海下的沉思
    【2020-03-28】Dubbo源码杂谈
    【2020-03-21】Dubbo本地环境搭建-实现服务注册和消费
  • 原文地址:https://www.cnblogs.com/1625--H/p/9824516.html
Copyright © 2011-2022 走看看