[数论第一节]质数/约数

这篇具有很好参考价值的文章主要介绍了[数论第一节]质数/约数。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

  • 数论

    • 质数

      • 在大于1的整数中,只包含1和本身这两个约数,就被称为质数,也叫素数
      • 质数的判定
        • 试除法
          • 遍历2-n,若有约数则不为质数 O(n)
          • 优化:
            • d整除n,则n/d也整除n,约数总是成对出现,只要找较小的约数,即取d <= n/d,则d <= sqrt(n) 只用遍历2-sqrt(n) O(sqrt(n))
            • 不用 i * i <= n ,i过大会溢出
            • sqrt()函数较慢,只用遍历 d--n/d,即限制范围为 i--n/i
          • 代码:
            //不用for(int i = 1; i * i <= n; ++ i) i * i 会溢出
            //不用for(int i = 1; i <= sqrt(n); ++ i) sqrt() 函数缓慢
            //用for(int i = 1; i <= n / i; ++ i)  不会溢出,快
            bool is_prime(int x){
            	if(x < 2) return false;
            	for(int i = 2; i <= n / i; ++ i)
            		if(n % i == 0) return false;
            	return true;
            }
            
      • 分解质因数
        • 试除法
          • 遍历2-n,找因子
          • n最多有一个大于sqrt(n)的因子,因此只用在2-sqrt(n)中找因子,最后判断最后一个因子是否为大于sqrt(n)的因子
          • 代码:
            //暴力做法
            void divide(int n){
            	for(int i = 2; i <= n; ++ i){
            		if(n % i == 0){
            			int s = 0; //i的个数
            			while(n % i == 0){
            				n /= i; //除干净
            				s ++ ;
            			}
            			cout << i << s << endl;
            		}
            	}
            }
            //优化
            void divide(int n){
            	for(int i = 2; i <= n / i; ++ i){
            		if(n % i == 0){
            			int s = 0;
            			while(n % i == 0){
            				n /= i;
            				s ++ ;
            			}
            			cout << i << s << endl;
            		}
            	}
            	if(n > 2) cout << n << 1;//n就是最后大于sqrt(n)的因子
            }
            
      • 筛选质数
        • 埃氏筛法
          • 从2-n,将每个数的倍数删掉,那么剩下的数就是质数 O(nln(n))
          • 优化:
            • 任何一个合数都可以拆成若干素数之积,因此只用将素数的倍数删掉 O(nln(ln(n))) ~ O(n)
          • 代码:
            int primes[N];
            int st[N];//标记是否被筛过
            void get_primes(int n){
            	int cnt = 0;
            	for(int i = 2; i <= n; ++ i){
            		if(!st[i]){ //没有被筛过,说明是质数
            			primes[ ++ cnt] = i;
            			//筛该质数的所有倍数
            			for(int j = i + i; j <= n; j += i) st[j] = 1;
            		}
            	}
            }
            
        • 线性筛法
          • 数据大小在107左右线性筛法比埃氏筛法快一倍,106左右差不多
          • n只会被它的最的最小质因子筛掉,利用最小质因子筛掉合数
          • 代码:
            int primes[N];
            int st[N];
            void get_primes(int n){
            	int cnt = 0;
            	for(int i = 2; i <= n; ++ i){
            		if(!st[i]) primes[ ++ cnt] = i;//没有被筛掉就是质数
            		for(int j = 1; primes[j] <= n / i; ++ j){//从小到大遍历质数
            			st[primes[j] * i] = 1; //筛掉合数,若x是合数,当i遍历到x时,一定会先遍历到x的最小质因子prime,所以此时prime进入primes数组,当i遍历到x/prime时,x = prime*i会被筛掉,所以每个合数都能被筛掉,并且是在遍历到该合数之前被筛掉
            			if(i % pimes[j] == 0) break; //i是合数筛掉i,i在之前就被标记过,所以不用再标记
            		} 
            	}
            }
            
    • 约数

      • 求所有约数

        • 试除法
          • 代码:
            vector<int> get_divisors(int n){
            	vector<int> res;
            	for(int i = 1; i <= n / i; ++ i){
            		if(n % i == 0){
            			res.push_back(i);
            			if(i != n / i) res.push_back(n / i);
            		}
            	}
            	sort(res.begin(), res.end());
            	return res;
            }
            
      • 约数的个数

        • \(N = p_1^{a_1} · p_2^{a_2} · p_3^{a_3} ··· ·p_n^{a_n}\) 其中p为N的所有质因子
        • 则N的约数个数为:\((a_1+1)(a_2+1)(a_3+1)···(a_n+1)\)
          • 代码:
            const int mod = 1e7 + 10;
            unordered_map<int, int> primes;//hash表存储每个质数有多少
            void get_primes(int n){
            	for(int i = 2; i <= n / i; ++ i){
            		while(n % i == 0){
            			n /= i;
            			primes[i] ++ ;
            		}
            	}
            	if(n > 1) primes[n] ++ ;
            }
            for(int i = 1; i <= n; ++ i) get_primes(a[i]);
            long long res = 0;
            for(auto p : primes) res = res * (p.second + 1) % mod;
            
        • 则N的约数总和为:\((p_1^{0}+p_1^{2}+···+p_1^{n})(p_2^{0}+p_2^{1}+···+p_2^{n})···(p_n^{0}+p_n^{1}+···+p_n^{n})\)
          • 代码:
            const int mod = 1e7 + 10;
            unordered_map<int, int> primes;
            void get_primes(int n){
            		for(int i = 2; i <= n / i; ++ i){
            			while(n % i == 0){
            				n /= i;
            				primes[i] ++ ;
            			}
            		}
            		if(n > 1) primes[n] ++ ;
            	}
            	for(int i = 1; i <= n; ++ i) get_primes(a[i]);
            	long long res = 1;
            	for(auto p : primes){
            		long long t = 1;
            		int a = p.first, b = p.second;
            		while(b -- ) t = (t * a + 1) % mod;
            		res = res * t % mod;
            	}
            
      • 最大公约数

        • 辗转相除法(欧几里得算法)O(logn)
        • a|b, a|c, 则 a|(b+c), 则a|(bx + cy)
        • 求a与b的最大公约数,设其公约数为c,则c|a, c|b, c|(ax + by), 设a = kb + m, 则m = a - kb, 则c|m, 又m = a % b, 则 c|(a % b), 即a与b的最大公约数,也是a%b的公约数,即gcd(a, b) = gcd(b, a % b)
        • 代码:
          int gcd(int a, int b){
          	return b ? gcd(b, a % b) : a;
          }
          

文章来源地址https://www.toymoban.com/news/detail-633014.html

到了这里,关于[数论第一节]质数/约数的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数论 --- 约数和定理公式推导、最大公约数、欧几里得算法

    和试除法判断一个数是不是质数是一个道理 从小到大枚举所有的约数,如果当前数能整除这个数的话,说明这个数就是当前数的约数 优化,与试除法判断质数是一样的 如果 d 是 n 的约数,n / d 也一定能整除 n,一个数的约数也一定是成对出现的,在枚举的时候也可以只枚举

    2023年04月08日
    浏览(86)
  • 关于质数筛——数论

    埃式筛法  欧拉筛

    2024年02月15日
    浏览(34)
  • C++数论————质数筛法(单独判断一个数,判断N个数) 埃氏筛法

    质数想必大家都不陌生 从小学到大 质数的概念: 一个数如果除了1和本身之外没有其他的因子,那么这个数被称为质数 今天要讲两个知识点: 在C++中如何判断一个数是否为质数 在C++中如何判断1-N之间哪些数为整数 在C++中如何判断一个数是否为质数 这个知识点较为简单 充分

    2023年04月08日
    浏览(50)
  • e[2333333, 23333333] 中有多少个正整数 可以被分解为 12 个质数相乘?

    任何一个大于 1 的正整数都能被分解为若干个质数相乘, 比如 28=2 times 2 times 728=2×2×7 被分解为了三个质数相乘。请问在区间 [2333333, 23333333] 中有多少个正整数 可以被分解为 12 个质数相乘? 答案提交 这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一

    2023年04月08日
    浏览(43)
  • Element UI el-input 只能输入大于0的正整数

    当输入值以0开头或者不为0-9的整数时,则用\\\' \\\'替换掉(/g表示全局匹配,则所有匹配项都会被替换掉),效果为不能输入以0开头或不为正整数的值。

    2024年02月14日
    浏览(61)
  • 第一章-第一节-会计概念、职能和目标

    东方欲晓,莫道君行早,踏遍青山人未老,风景这边独好。虽然我的专业是软件工程,但是!但是!但是!光有技术是不够的,我自认为我也不是天才,我只是一个普通人,所以除了技术,我应该掌握一点别的什么东西,想赚钱,却不了解相关的知识,嗯,那就考个初级会计

    2024年01月19日
    浏览(46)
  • 基本环境准备(第一节)

    基本环境准备(第一节) 2023年8月9日 16:37   1.安装Node.js; Windows 上安装 Node.js 你可以采用以下两种方式来安装。 1、Windows 安装包(.msi) 本文实例以 v0.10.26 版本为例,其他版本类似, 安装步骤:   步骤 1 : 双击下载后的安装包 v0.10.26,如下所示: 步骤 2 : 点击以上的Run(运行),将

    2024年02月13日
    浏览(43)
  • 第一节 RobotFramework环境搭建

    1 robotframework的环境搭建 第一步:Python环境(建议3.6.8)     首先安装python ,可从如下地址下载:     https://www.python.org/downloads/release/python-368/     安装成功后配置到环境变量     然后启一个cmd命令窗口验证下是否成功安装,成功安装如图所示: 第二步:robotframwwork安装

    2023年04月09日
    浏览(43)
  • 相机成像原理【第一节】

    1、胶片摄影与数码摄影 胶片摄影是把光学镜头的光信号投射到胶片上, 数码摄影是把光学镜头的光信号投射到传感器上,传感器把光信号依次处理为电信号和数字信号,片上计算机再把数字信号进行处理 2、相机的组成 2.1 只有传感器相机的成像 一棵树所有的点发出的光照

    2024年02月12日
    浏览(43)
  • 第一节——单片机概述

    1.MCD-51单片机  与8051(80C51) 兼容的主要产品 ATMEL公司生产的兼容51单片机的具体型号 2.AVR系列单片机 AVR系列是1997年ATMEL公司挪威设计中心的A先生与V先生共同研发出的精简指令集(RISC—Reduced Instruction Set Computer)的高速8位单片机,简称AVR。  AVR单片机系列全,3个档次,适于各

    2024年01月24日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包