首页 > 其他分享 >数论第一节

数论第一节

时间:2023-08-06 17:44:14浏览次数:32  
标签:约数 get 数论 质数 第一节 int 因子 primes

  • 数论

    • 质数

      • 在大于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;
          }
          

标签:约数,get,数论,质数,第一节,int,因子,primes
From: https://www.cnblogs.com/moilip/p/17609665.html

相关文章

  • 【学习笔记】数论之筛法
    前言:可以会乱记一些技巧吧。交换求和顺序如果不确定可以将条件写成[A]的形式,交换完求和顺序再把这个条件放里面。例如:\[\sum_{i=1}^n\sum_{d}[d|i]=\sum_{d=1}^n\sum_{i}[d|i]=\sum_{d=1}^n\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}1\]狄利克雷前缀和与狄利......
  • 第一节 变量与字符串
                                                  第一节  变量与字符串   1.变量不用类型定义直接赋值x=3name="小甲鱼"age='5'x=y=32.print()括号里可以用单引号,双引号输出字......
  • 第一节:Lvs软件负载技术详解
    一.        二.        三.         !作       者:Yaopengfei(姚鹏飞)博客地址:http://www.cnblogs.com/yaopengfei/声     明1:如有错误,欢迎讨论,请勿谩骂^_^。声     明2:原创博客请在转载......
  • 数论函数
    P1390公约数的和简单莫反题。要求\[\sum_{i=1}^{n}\sum_{j=i+1}^ngcd(i,j)\]可以先考虑问题的简化版:\[\sum_{i=1}^{n}\sum_{j=1}^ngcd(i,j)\]\[=\sum_{d=1}^nd\sum_{i=1}^{n}\sum_{j=1}^n[gcd(i,j)==d]\]\[=\sum_{d=1}^nd\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1......
  • 解析数论之原根
    解析数论之原根目录Chapter1什么是整数的次数,什么是原根Chapter2谁有原根?Chapter1什么是整数的次数,什么是原根Definition:对于\((a,m)=1,m\ge1\),考虑所有\(a,a^2,a^3,\cdots\),我们通过欧拉定理知道有\(a^{\varphi(m)}\equiv1\mod{m}\)。而满足\(a^f\equiv1\mod{m}\)......
  • 0801数论
    GCD&exGCD首先我们考虑辗转相除法的过程,因为\((a,b)=(b\bmoda,a)(0<a<b)\),\((0,b)=b\),所以我们就可以每次将\(b\)转化为严格更小的\(b\)的问题。归纳则得到答案。现在我们考虑扩欧的过程,我们需要对\(ax+by=1\)找到一组解。那么我们实际上就是要对一个形如\((a,b)\)......
  • 20230801 数论基础学习笔记
    理论基础中国剩余定理及拓展已知\(x\equiva_i(\bmodp_i\)\),求\(x\bmod\operatorname{lcm}\{p_i\}\)的值。若\(p_i\)互质,那么我们只需要计算\(c_i\)使得\[\prod\limits_{j\nei}\cdotc_i\bmodp_i=1\]然后有\[x=\sum\limits_{i}c_ia_i\prod\limits......
  • 通过求逆元的几种方式复习基础数论
    逆元若\(ax=1\pmodp\),那么称\(a\)是\(x\)的逆元,显然\(x\)也是\(a\)的逆元。两边同时除以\(a\)得到\(x=\frac1a\pmodp\),可以写成\(x=a^{-1}\pmodp\),这么看来,乘法逆元就是取模意义下的倒数啊。若\(p\)为质数,\(0\)没有逆元,\(1\)的逆元是\(1\),\(p-1\)的逆元......
  • 数论
    1.桌球问题矩形球桌四个角有洞yx坐标在(0,0)(m,0)(m,n)(0,n)球从(0,0)沿45度方向无限大力发射,求mn满足啥条件能落袋解法:这种桌球问题只要无限延伸方块就行,相当于解y=x有没有(am,bn)解,其中a和b是整数。m和n如果是正整数,n*m=m*n,肯定落袋;如果是......
  • 【模板】数论基础:exGCD,exCRT,inverse,Lucas,BSGS,primitive root
    7.29数论WIP\(a\equivb\pmodp\Rightarrow\frac{a}{d}\equiv\frac{b}{d}\pmod{\frac{p}{d}},d=\gcd(a,b,p)\)。exGCD若\((a,b)=1\),则\(0\leqx<b\),\(ax\bmodb\)互不相同,有一个是\(1\)。证明:\(ax_1\equivax_2\pmodb\)则\((x_1-x_2)a|b\),因为......