首页 > 其他分享 >学习笔记——数论

学习笔记——数论

时间:2024-07-01 11:31:46浏览次数:1  
标签:约数 ... frac 数论 质数 笔记 学习 int alpha

写在前面...
通过写数论的md笔记,新知识不确定有没有学懂,但是我的md数学公式方法得到了极大的提升orz

质数的定义:

针对从2开始的整数定义,如果只包含1和本身这两个因数,则称该数为质数(素数)

(1)质数的判定:试除法

枚举因数的时候,只枚举到因数比较小的那个范围(根号n)

(2)分解质因数:试除法

从小到大枚举所有的数,对于质因子,可通过循环求出每个质因子的个数,从小往大除可以保证其因子一定是质数。

且\(n\)中最多只包含一个大于\(sqrt(n)\)的质因子

朴素筛法时间复杂度为\(O(nlogn)\)

1. 埃式筛法

定义及其原理:

每个合数都可以表示为多个质数的积,因此从最小的质数2开始,用每一个已找到的质数去筛选比它大的数,从而筛掉合数,剩下的就是素数。

算法过程:

1)从最小的质数2开始,遍历\(n\)以内的所有数\(i\)

2)对于当前数\(i\), 判断其是否是质数,如果是,则用\(i\)筛掉其在范围内的所有倍数,如\(i=3\)时,筛掉\(n\)以内的所有\(3\)的倍数。

3)不断重复过程2,直到遍历到\(n\)

时间复杂度\(O(nloglogn)\)

2. 线性筛法

原理:n只会被最小质因子筛掉,且合数一定会被筛掉

1) \(i\) % \(prime[j] == 0\)时:

\(prime[j]\)一定是\(i\)的最小质因子,且\(prime[j]\)一定是\(prime[j]*i\)的最小质因子

2) \(i\) % \(prime[j] != 0\)时:

\(prime[j]\)一定小于\(i\)的所有质因子,且\(prime[j]\)也一定是\(prime[j]*i\)的最小质因子

const int N = 10000010;
int primes[N], cnt;
bool st[N];

void get_primes(int n){
   for(int i = 2; i <= n; i++){
   	if(!st[i])	primes[cnt ++] = i;
   	//j从小到大枚举所有质数
   	for(int j = 0; primes[j] <= n / i; j++){
   		st[primes[j] * i] = true;
   		//当该条件成立的时候, prime[j]一定是i的最小质因子
   		if(i % primes[j] == 0)	break;
   	}
   }
}

质数定理

\(1~n\)中,有\(n/logn\)个质数

3. 约数

1)试除法求一个数的所有约数

从小到大枚举所有可能的数字,时间复杂度为\(O(logn)\)

2) 求约数个数

当\(N = p_1^{\alpha_1}* p_2^{\alpha_2}*...*p_k^{\alpha_k}\)

对于一个数的所有约数,一定可以由上面的通式来表示,且有所对应的\(\alpha_1\)、\(\alpha_2\)、\(\alpha_3\)。

约数用M表示,那么\(M = p_1^{\beta_1}* p_2^{\beta_2}*...*p_k^{\beta_k}\)

对于\(\beta_1\)、\(\beta_2\)、\(\beta_3\)的取值范围,为\(0~\)~\(\alpha_i\),就能够表示出来所有的约数。所以求约数个数实际可拆解为组合数学(乘法原理)。

所以对于N而言,其对应的约数个数为\((\alpha_1+1)*(\alpha_2+1)*(\alpha_3+1)...(\alpha_k+1)\)

计算时间复杂度

对于i而言,n以内所有倍数的个数表示为\(n/i\)

所以n以内所有数的倍数个数表示为\(\sum_{i=1}^{i=n}{n/i}\)

3)求约数之和(没懂)

根据乘法原理和加法原理,约数之和可以表示为:

\(({p_1}^0+{p_1}^1+...+{p_1}^{\alpha_1})*({p_2}^0+{p_2}^1+...+{p_2}^{\alpha_2})*...*({p_k}^0+{p_k}^1+...+{p_k}^{\alpha_k})\)

4)欧几里得算法(辗转相除法)

求两数的最大公约数

通过原理:如果a能整除d,且b能整除d,那么ax+by也能够整除d,可推:

\(gcd(a,b)=gcd(b,a-c*b)\)

int gcd(int a, int b){
	return b ? gcd(b, a % b) : a;
}

4. 欧拉函数

\(\phi(n)\)表示为1到\(n\)中和n互质的数的个数

\(p_1\)、\(p_2...\)\(p_n\)表示n的所有质因子

若\(n={p_1}^{\alpha_1}*{p_2}^{\alpha_2}*...*{p_k}^{\alpha_k}\)

那么\(\phi(n)=n*(1-\frac{1}{p_1})*(1-\frac{1}{p_2})*...*(1-\frac{1}{p_k})\)

其时间复杂度为\(O(\sqrt{n})\)

该公式的证明需要用到容斥原理

方法:

从1~n中删掉所有\(p_1\)、\(p_2...\)\(p_n\)的倍数,那么剩下的数的个数就可以表示成\(n-\frac{p_1}{n}-\frac{p_2}{n}-...-\frac{p_k}{n}\),但是这样会重复删除掉某些倍数

加上所有\(p_i*p_j\)的倍数的个数,因为这些数被删掉了两次,其个数可以表示为\(\frac{p_i*p_j}{n}\)

减去所有\(p_i*p_j*p_k\)的个数,其个数表示为\(\frac{p_i*p_j*p_k}{n}\)

一直重复上述过程,偶数因子数要加上,奇数因子数要减掉,直到覆盖掉所有的因子数。这个公式最后就可以由上面\(\phi(n)\)的式子表示

代码实现

int n;
cin >> n;
while(n--){
	int a;
	cin >> a;
	for(int i = 2; i <= a / i; i++){
		if(a % i == 0){
			res = res / i * (i - 1);
			while(a % i == 0)	a %= i;
		}
	}
	//最后如果还有剩 
	if(a > 1)	 res = res / a * (a - 1);
	cout << res << endl;
}

筛法计算欧拉函数

可以通过线性筛来算某一个数的所有质数,从而提高求欧拉函数的效率。

ll get_eulers(int n){
	phi[1] = 1;
	for(int i = 2; i <= n; i++){
		//如果i到当前还没有被筛掉的话,则证明i是一个质数
		if(!st[i]){
			primes[cnt ++] = i;
			//1~i-1以内与质数i互质的个数有
			phi[i] = i - 1;
		}
		//把所有i的倍数都筛掉
		for(int j = 0; primes[j] <= n / i; j++){
			st[primes[j] * i] = 1;
			if(i % primes[j] == 0){
				//公式推导,求i*prime[j]的质因子个数
				phi[i * primes[j]] = phi[i] * primes[j];
				break;
			}
			phi[i * primes[j]] = phi[i] * (primes[j] - 1);
		}
	}
	ll res = 0;
	for(int i = 1; i <= n; i++)		res += phi[i];
	return res;
}

欧拉定理

如果\(a\)和\(n\)互质,那么\(a^{\phi(n)}\equiv1(mod\quad n)\)

费马小定理

如果\(n\)是一个质数,且\(a\)和\(n\)互质,那么\(a^{n-1}\equiv1(mod\quad n)\)

5. 快速幂

快速幂:快速求解\(a\)的\(k\)次方模\(p\)的结果,其时间复杂度为\(O(logk)\)

其核心思路是预处理出来\(a^{2^0}\)\(a^{2^2}\)...\(a^{2^k}\)的模p下的值

\(a^k\) = \(a^{2^i}\) * \(a^{2^j}\) * \(a^{2^k}\)... = \(a^{2^i+2^j+2^k+...}\)

该式子即把k以二进制的形式表示。

int quick_mi(int a, int k, int p){
	int res = 1;
	while(k){
		if(k & 1)	res = (ll)res * a % p;
		k >>= 1;
		a = (ll)a * a % p;
	}
	return res;
}

快速幂求逆元

逆元:如果\(a\)能够整除\(b\),希望找到一个数,实现\(\frac{a}{b}\equiv a*x(mod\quad p)\)

这个数\(x\)即叫做\(b\)模\(p\)的逆元,记做\(b^{-1}\),所以\(\frac{a}{b}\equiv a*b^{-1}(mod\quad p)\)

左右两边把\(a\)删掉,同乘一个\(b\),也就是\(b*b^{-1}\equiv1(mod\quad p)\)

由费马小定理可得到,如果\(p\)是质数,且\(b\)和\(p\)互质,那么\(b^{p-1}\equiv1(mod\quad p)\),得到\(b*b^{p-2}\equiv1(mod\quad p)\)

对比逆元的公式,如果b是质数,那么b的逆元即等于\(b^{p-2}\),即可以利用快速幂求解\(b^{p-2}\)

int res = quick_mi(a, p-2, p);
//如果a和p互质,那么a的p-2次方即为逆元
if(a % p != 0)		printf("%d\n", res);
//如果p是a的因子,那么对于a而言,不存在逆元
else		print("impossible");

6. 扩展欧几里得算法

裴蜀定理

对于任意一对正整数\(a\)和\(b\),一定存在非零整数\(x\)和\(y\),使得\(ax + by=gcd(a, b)\)

利用扩展欧几里得算法来求其系数\(x\)和\(y\)

int exgcd(int a, int b, int &x, int &y){    
	//b==0时找到结果
	if(!b){
		x = 1, y = 0;
		return a;
	}
	int d = exgcd(b, a % b, y, x);
	//公式推导
	y -= a / b * x;
    return d;
}

int main(){
	int a, b, x, y;
	scanf("%d %d %d %d", &a, &b, &x, &y);
	exgcd(a, b, x, y);
}

公式推导

边界条件:

当\(b==0\)时,\(gcd(a, 0)=a\)

又因为\(ax + by=gcd(a, b)\)

所以\(ax+by=a\),\(x=1\),\(y=0\)

递归情况:

\(ax + by=gcd(a, b)=gcd(b, a\) \(mod\) \(b)\)

交换x、y,把\(a\)用\(b\)代替,b用 \(a\) mod \(b\) 代替,\(d\)为\(gcd(a,b)\),那么

\(by+(a\) \(mod\) \(b)x=d\)

\(by+(a-\lfloor{\frac{a}{b}}\rfloor b)x=d\)

\(ax+(y-\lfloor{\frac{a}{b}}\rfloor x)b=d\)

所以递归后的系数,\(x\)保持不变,\(y\)变成\(y-\lfloor{\frac{a}{b}}\rfloor x\)

标签:约数,...,frac,数论,质数,笔记,学习,int,alpha
From: https://www.cnblogs.com/hsy2093/p/18277715

相关文章

  • sql-labs通关笔记(上)
    sql-labs通关笔记(上)这里我们先只讲解less-1到less-9联合查询注入Less-1:GET-Errorbased.Singlequotes-string界面在url中加入?id=1?id=-1判断注入点使用’或\来判断是否存在注入点payloadhttp://127.0.0.1/sqli/Less-1/?id=-1'报错信息near''-1''LIMIT0......
  • vue学习笔记4
    1.数组变化侦测<template><div>数组变化侦听</div><buttonv-on:click="addListHandler">添加数据</button><ul><liv-for="(item,index)innames":key="index">{{item}}</li></ul><......
  • 开源项目相关:ChatGPT学习过程
    大规模无标注数据预训练:ChatGPT首先使用大规模的无标注数据进行预训练。例如,它可能使用了8.5亿对话对来学习对话的表达与交互方式。这一步主要依赖Transformer等神经网络结构,通过预测下一个词来学习语言的统计规律和语义知识。自监督学习:在预训练过程中,ChatGPT将对话划分为utt......
  • python pyqt5学习记录(一)
    了解pyQt5:PyQt5是一个用于创建图形用户界面(GUI)应用程序的Python库。它是Python编程语言与Qt应用程序框架的绑定,允许开发人员使用Python语言来创建跨平台的桌面应用程序。Qt是一个功能强大且广泛使用的C++库,用于开发图形界面和应用程序功能。关于PyQt5的一些重要信息和功能:1.......
  • 阅读笔记《GB/T28449-2018信息安全技术网络安全等级保护测评过程指南》
    方案编制:测评对象确定、测评指标确定、测评内容确定、工具测试方法确定、测评指导书开发、测评方案编制对每项活动均给出相应的工作流程、主要任务、输出文档及活动中的相关方的职责的规定,每项工作任务均有相应的输入、任务描述和输出产品测评风险:影响系统正常运行、感信息泄露......
  • ArchiMate 3 学习
    目录ArchiMate3学习什么是ArchiMateArchiMate3.1规范关系动机元素策略元素业务层应用层技术层物理元素实施和迁移元素复合元素ArchiMate3学习ArchiMate3中文版什么是ArchiMateArchiMate是TheOpenGroup为企业架构提供的开放和独立的建模语言,由不同的工具供应商和......
  • AI引到学习前端开发
    假设你是一位前端技术开发专家,我有几个JavaScript的问题想向你咨询我想用JavaScript来做微信小程序开发,请以表格的方式输出知识要点请叙述JavaScript操作浏览器对象的常用接口和方法把上述表格按照访问对象归类将上述文字制作一个表格来呈现,要求逻辑清晰描述信息简明扼要且......
  • Diffusers代码学习:加载适配器
    有几种用于个性化扩散模型以生成特定主题的图像或特定风格的图像的训练技术。每种训练方法都会产生不同类型的适配器。一些适配器生成一个全新的模型,而其他适配器只修改一组较小的嵌入或权重。这意味着每个适配器的加载过程也不同。DreamBooth仅在一个主题的几个图像上微调整......
  • 《昇思25天学习打卡营第2天 | 张量 Tensor》
    《昇思25天学习打卡营第2天|张量Tensor》《昇思25天学习打卡营第2天|张量Tensor》《昇思25天学习打卡营第2天|张量Tensor》什么是张量(Tensor)张量的创建方式根据数据直接生成从NumPy数组生成使用init初始化器构造张量继承另一个张量的属性,形成新的张量张量的属......
  • 《昇思25天学习打卡营第3天 | 数据集 Dataset》
    《昇思25天学习打卡营第3天|数据集Dataset》《昇思25天学习打卡营第3天|数据集Dataset》《昇思25天学习打卡营第3天|数据集Dataset》什么是数据集MindSpore的数据集数据集加载数据集迭代数据集常用操作mapbatch自定义数据集可随机访问数据集可迭代数据集生成......