数论<1>——数论基础

news2025/6/20 12:59:43

这期博客是一个数论入门介绍,dalao们可以自动忽略。

Part 1:素数(质数)

说到数论,小学奥数里也有。我最先想到的就是质数了。素数就是一个只能被1和它自己整除的数。判断的方法也很简单,可以\Theta (n)扫一遍就结束了,但是没必要。由于一个数的因数肯定分布在\Theta (\sqrt{n})的左边和右边。因此,只用扫描到\sqrt{n}就够了。

bool isprime(int n){
	if(n<2)//0和1都不是质数 
		return false;
	for(int i=2;i<=n/i;i++){//这里i<=n/i是一个防止i*i爆int以及sqrt(n)精度不好的小技巧 
		if(n%i==0)
			return false;
	}
	return true;
}

现在,我们知道如何判断一个数是不是质数的方法了。现在,我们向分解G(质因)数。我们\Theta (\sqrt n)的扫描,只要i是n的因数,就把i塞进一个map里,然后除掉n里面所有的i。这样就保证了每个i都是素数,顺便记录次数。最后,有可能n不为0,所以要特判。

map<int,int> fac;//分别是:质因子,次数
for(int i=2;i<=n/i;i++){
	if(n%i==0){
		while(n%i==0){
			n/=i;
			fac[i]++;
		}
	}
}
if(n)//特判
	fac[n]=1;

在这里,我补充几个公式:

唯一分解定理:N=p_{1}^{\alpha _{1}} \cdot p_{2}^{\alpha _{2}} \cdot ......\cdot p_{k}^{\alpha_{k}}

因数个数定理:(\alpha_{1}+1)\cdot (\alpha_{2}+1) \cdot ......(\alpha_{k}+1)

因数和定理:(p_{1}^{0}+p_{1}^{1}+...+p_{1}^{\alpha_{1}})\cdot (p_{2}^{0}+p_{2}^{1}+...+p_{2}^{\alpha_{2}})\cdot ......\cdot (p_{k}^{0}+p_{k}^{1}+...+p_{k}^{\alpha_{k}})

-------------------------------------------------华丽的分割线--------------------------------------------------------

接下来,我们来谈一个比较有意思的东西。首先,如果我让你打印100以内的素数表,你会怎么做?根据刚刚的判断素数的方法,我们可以\Theta (n \sqrt{n})的解决这个问题。但是如果数据放大到10^6甚至10^7,怎么办?

这就要用到素数筛了。素数筛就是一种算法,可以帮你快速筛出素数。有两种筛法,埃筛和欧筛。分别由欧拉和bla~bla~(埃拉托色尼)发明的。先说埃氏筛法(因为好懂),这个算法的核心就是素数的倍数一定是合数。然后,我们就可以愉快的写代码了。

bool isprime[maxn];
void sieve(){
	memset(isprime,true,sizeof(isprime));
  	isprime[0]=isprime[1]=false;
  	for (int i=2;i<=maxn/i;i++){
    	if(isprime[i]){
      		for(int j=i*i;j<=maxn;j+=i)
	  			isprime[j]=false;
	  	}
  	}
}

埃筛的复杂度为\Theta (n \: log \: log \: n),略微有点高,但是好记。

接下来我们来看看复杂度接近\Theta (n)的欧拉筛。埃筛的问题在于素数会被标记多次,那我们优化的方法就是让合数只被标记一次。同时,欧拉筛也叫线性筛(复杂度是线性的嘛)。

bool notprime[maxn];
vector<int> prime;
void sieve(){
	notprime[1]=true;
  	for(int i=2;i<=maxn;i++){
    	if(!notprime[i])
      		prime.push_back(i);
    	for(int x:prime){
      		if(i*x>maxn)
			  	break;
      		notprime[i*x]=true;
      		if(i%x==0)
        		break;
    	}
  	}
}

注意,一定要用notprime,不然又回到埃筛了。

这里就不放例题了,因为其实就是板子。

Part 2:最大公因数和最小公倍数

最大公因数和最小公倍数都是小学奥数学过的东西。但还是稍微介绍一下吧。顾名思义,最大公约数是两个数最大的公约数,最小公倍数是两个数最小的公倍数。接下来,我们来看看如何求最大公约数和最小公倍数。

最大公约数:辗转相除法,即gcd(a,b)=gcd(b,a \: mod \: b) \: (a<b) 。证明嘛,我不大会,但......

OI-Wiki!

放个代码。

int gcd(int a,int b){
    if(b==0)
        return a;
    return gcd(a,b%a);
}
//当然,STL里有一个函数叫__gcd
//它也可以求gcd,所以我们就不用自己写啦(*^▽^*)

顺便说一句,如果gcd(a,b)=1,那我们称a,b互质。欧几里得算法时间复杂度\Theta (log \: max(a,b))

接下来看最小公倍数的求法。先给结论:

int lcm(int a,int b){
    return a*b/__gcd(a,b);
}

为什么?我们令a=p_1^{k_{a_{1}}}\cdot p_2^{k_{a_{2}}}\cdot ...\cdot p_s^{k_{a_{s}}},b=p_1^{k_{b_{1}}}\cdot p_2^{k_{b_{2}}}\cdot ...\cdot p_s^{k_{b_{s}}},那么:

(a,b)=p_1^{min(k_{a_{1}},k_{b_{1}})}\cdot p_2^{min(k_{a_{2}},k_{b_{2}})}\cdot ...\cdot p_s^{min(k_{a_{s}},k_{b_{s}})}

[a,b]=p_1^{max(k_{a_{1}},k_{b_{1}})}\cdot p_2^{max(k_{a_{2}},k_{b_{2}})}\cdot ...\cdot p_s^{max(k_{a_{s}},k_{b_{s}})}

由于k_a+k_b=max(k_a,k_b)+min(k_a+k_b),所以a\times b=lcm(a,b)\times gcd(a,b)

Part 3:扩展欧几里得

我们先来看一个方程:ax+by=c 而它,是终极大Boss。那么它什么时候有解呢?

(a,b)\mid c是,方程有解。So,c必然是gcd(a,b)的倍数。所以,我们先看ax+by=(a,b)的情况,这也是扩展欧几里得解决的问题。

根据欧几里得算法,得ax+by=gcd(a,b)=gcd(a,a \: mod \: b),接下来递归又变成了这个↓

bx+(a \: mod \: b)y=gcd(b, a \: mod \: b)。我们叫这个bx_1+(a \: mod \: b)y_1=gcd(b,a \: mod \: b)

然后就知道ax_0+by_0=bx_1+(a \: mod \: b)y_1,所以x_0=y_1,y_0=x_1-(a*b)/y_1

当你递归到最后一层,也就是b=0的时候,你就解得x'=1,y' \epsilon R。然后我们在向上递归,得出开

始的x和y。Talk is cheap,show me your code.

int exgcd(int a,int b,int &x,int &y){
	if(b==0){
		x=1;
		y=0;
		return a;
	}
	int res=exgcd(b,a%b,x,y);
	int tmp=x;
	x=y;
	y=tmp-a/b*y;
	return res;
}

说了这么多,来练练手吧。

P1082:

乍一看,你可能会问:这和扩展欧几里得有啥关系?问的有理,我们来做一些恒等变形。

ax\equiv 1(mod\:b)其实相当于ax+by=1。可这还是跟ax+by=(a,b)不一样啊,没关系。有

解的情况是c\mid gcd(a,b),而1一定满足。现在,它就变成了exgcd的板子题啦!

#include <bits/stdc++.h>
using namespace std;
//exgcd
int main(){
	int a,b,x,y;
	cin>>a>>b;
	int res=exgcd(a,b,x,y);
	if(x<0)
		x+=b;
	cout<<x<<endl;
	return 0;
}

ABC186E:

洛谷上也有。转圈,不难想到同余。

我们可以列出方程S+Kx\equiv 0\: (mod\: N),得Kx\equiv -S\: (mod \: N),再把右边加上N,解x就

ok了。和上一题相似。

#include <bits/stdc++.h>
using namespace std;
long long x,y;
long long exgcd(long long a,long long b){
	if(b==0){
		x=1;
		y=0;
		return a;
	}
	long long res=exgcd(b,a%b);
	long long tmp=x;
	x=y;
	y=tmp-a/b*y;
	return res;
}
long long main(){
	int T;
	cin>>T;
	while(T--){
		long long N,S,K;
		cin>>N>>S>>K;
		long long res=exgcd(K,N);
		long long t=(N-S)%N;
		if(t%res)
			cout<<-1<<endl;
		else
			cout<<(x%N+N)%N*(t/res)%(N/res)<<endl;	
	}
	return 0;
}

P1516:

这两个青蛙是真够笨的。

起点是a,b;速度是m,n;步数是t;套圈k次,得(m-n)t-lq=b-a。一个不定方程!所以用扩展

欧几里得算法求解。

//十年OI一场空,不开long long见祖宗
#include <bits/stdc++.h>
using namespace std;
int exgcd(int a,int b,int &x,int &y){
	if(b==0){
		x=1;
		y=0;
		return a;
	}
	int res=exgcd(b,a%b,x,y);
	int tmp=x;
	x=y;
	y=tmp-a/b*y;
	return res;
}
int main(){
	int a,b,m,n,l,t,q;
	cin>>a>>b>>m>>n>>l;
	if(m<n){
		swap(m,n);
		swap(a,b);
	}
	int res=exgcd(m-n,l,t,q);
	if((b-a)%res!=0){
		cout<<"Impossible"<<endl;
		return 0;
	}
	int ans=t*(b-a)/res;
	int step=l/res;
	ans%=step;
	if(ans<0)
		ans+=step;
	cout<<ans<<endl;
	return 0;
}

 好了Y(^o^)Y,以上就是本期的全部内容了。我们下期再见!

友情提醒:本期的题解代码都有问题,请不要无脑Ctrl C+Ctrl V

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1503396.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用yarn创建vite+vue3electron多端运行

文章目录 第一步 使用yarn创建vite+vue3项目遇到创建报错看第二步 引入electron第三步 创建main.js在electron下面的main.js写入下面代码第四步 安装同时运行多条命令npm包&&修改package.json文件npm包增加一条electron运行脚本命令效果图第一步 使用yarn创建vite+vue3…

[Electron]中IPC进程间通信

Electron中IPC 进程间通信 (IPC) 是在 Electron 中构建功能丰富的桌面应用程序的关键部分之一。在 Electron 中&#xff0c;进程使用 ipcMain 和 ipcRenderer 模块&#xff0c;通过开发人员定义的“通道”传递消息来进行通信。 本文介绍以下几个方面&#xff1a; 1-渲染进程到…

SpringCloud基础

SpringCloud基础环境 1、基本环境版本选择 Java&#xff1a; Java17&#xff1b;spring cloud&#xff1a;2023.0.0&#xff1b;spring boot&#xff1a;3.2.0&#xff1b;cloud alibaba&#xff1a;2022.0.0.0-RC2&#xff1b;Maven&#xff1a;3.9&#xff1b;Mysql&#x…

SQL设计时增加说明列

后关闭sql Studio,然后打开注册表,注册表地址: 计算机\HKEY_CURRENT_USER\SOFTWARE\Microsoft\SQL Server Management Studio\18.0_IsoShell\DataProject 如有版本不同,红色内容有所变化,修改内容如下: SSVPropViewColumnsSQL70,SSVPropViewColumnsSQL80 全修改为 1,2,6,7…

SHA算法:数据完整性的守护者

title: SHA算法&#xff1a;数据完整性的守护者 date: 2024/3/9 20:38:59 updated: 2024/3/9 20:38:59 tags: SHA算法起源安全性演进碰撞攻击风险数据完整性验证数字签名应用Python实现示例算法优势对比 一、SHA算法的起源与演进 SHA&#xff08;Secure Hash Algorithm&#…

深度学习:如何面对隐私和安全方面的挑战

深度学习技术的广泛应用推动了人工智能的快速发展&#xff0c;但同时也引发了关于隐私和安全的深层次担忧。如何在保护用户隐私的同时实现高效的模型训练和推理&#xff0c;是深度学习领域亟待解决的问题。差分隐私、联邦学习等技术的出现&#xff0c;为这一挑战提供了可能的解…

16. C++标准库

C标准库兼容C语言标准函数库&#xff0c;可以在C标准库中直接使用C语言标准函数库文件&#xff0c;同时C标准库增加了自己的源代码文件&#xff0c;新增文件使用C编写&#xff0c;多数代码放在std命名空间中&#xff0c;所以连接C标准库文件后还需要 using namespace std;。 【…

Java高频面试之并发篇

有需要互关的小伙伴,关注一下,有关必回关,争取今年认证早日拿到博客专家 并行和并发有什么区别&#xff1f; 并行是同时执行多个任务&#xff0c;而并发是多个任务在一段时间内交替执行。并行&#xff08;Parallel&#xff09;是指同时执行多个任务或操作&#xff0c;通过同时…

腾讯云轻量应用服务器限制月流量,你知道吗?

腾讯云轻量应用服务器相对于云服务器CVM是有一些限制的&#xff0c;比如轻量服务器不支持更换内网IP地址&#xff0c;不支持自定义私有网络VPC&#xff0c;内网连通性方面也有限制&#xff0c;轻量不支持CPU内存、带宽或系统盘单独升级&#xff0c;只能整个套餐整体升级&#x…

11. 搭建较通用的GoWeb开发脚手架

文章目录 导言一、加载配置二、初始化日志三、初始化MySQL连接四、初始化Redis连接五、初始化gin框架内置的校验器使用的翻译器六、注册路由七、 启动服务八、测试运行九&#xff1a;注意事项 代码地址&#xff1a;https://gitee.com/lymgoforIT/bluebell 导言 有了前述知识的…

matlab读取hdf5格式的全球火灾排放数据库Global Fire Emissions Database(GFED)数据

1.引言 火灾是大气中痕量气体和气溶胶的重要来源&#xff0c;并且是全球尺度上最重要的干扰因素。此外&#xff0c;森林砍伐和热带泥炭地火灾以及火灾频率增加的地区&#xff0c;都会增加大气中二氧化碳的积累。烧毁面积提供了生物质燃烧事件期间受火灾影响土地的估算&#xff…

数据结构:Heap(二叉树)的基本操作

目录 1.有关二叉树必须知道的几个基本概念 2.有关二叉树的基本操作 2.0有关元素的定义以及要进行的操作 2.1初始化和销毁操作 2.2插入操作以及上调操作 2.2.1插入操作以及上调操作的图解 2.2.2插入操作以及上调操作的代码 2.3删除根元素及其下调操作 2.3.2删除根元素及…

基于Java的社区买菜系统(Vue.js+SpringBoot)

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、系统设计2.1 功能模块设计2.1.1 数据中心模块2.1.2 菜品分类模块2.1.3 菜品档案模块2.1.4 菜品订单模块2.1.5 菜品收藏模块2.1.6 收货地址模块 2.2 可行性分析2.3 用例分析2.4 实体类设计2.4.1 菜品分类模块2.4.2 菜品档案模块2.4.3…

Solidity攻击合约:重入攻击与危害分析

以太坊智能合约开发中&#xff0c;重入攻击是一种常见的安全漏洞。这种攻击通常发生在合约的递归调用中&#xff0c;攻击者通过构造恶意交易&#xff0c;使得原本合约在执行过程中不断调用自身或其他合约&#xff0c;从而耗尽合约的Gas&#xff08;交易费用&#xff09;&#x…

基于java ssm springboot女士电商平台系统

基于java ssm springboot女士电商平台系统源码文档设计 博主介绍&#xff1a;多年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 央顺技术团队 Java毕设项目精品实战案例《1000套》 欢迎点赞 收藏 ⭐留言 文末…

uniapp发行H5获取当前页面query

阅读uni的文档大致可得通过 onLoad与 onShow()的形参都能获取页面传递的参数&#xff0c;例如在开发时鼠标移动到方法上可以看到此方法的简短介绍 实际这里说的是打开当前页面的参数&#xff0c;在小程序端的时候测试并无问题&#xff0c;但是发行到H5时首页加载会造成参数获取…

Nginx实现高并发

注&#xff1a;文章是4年前在自己网站上写的&#xff0c;迁移过来了。现在看我之前写的这篇文章&#xff0c;描述得不是特别详细&#xff0c;但描述了Nginx的整体架构思想。如果对Nginx玩得透得或者想了解深入的&#xff0c;可以在网上找找其他的文章。 ......................…

练习ROS动作编程

ROS学习记录&#xff1a;动作编程 引言&#xff1a; ​ 通过本实验&#xff0c;我们将联系我们学过的动作编程&#xff0c;客户端发送一个运动目标,模拟小乌龟运动到目标位置的过程,包含服务端和客户端的代码实现&#xff0c;并且带有实时的位置反馈。 希望你在本次学习过后&am…

html--心花怒放

代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><title>Canvas 绘制一个❤</title><link rel"shortcut icon" href"../../assets/images/icon/favicon.ico" type"ima…

Edge好用的插件

目录 浏览器下载插件 插件推荐 AdGuard 广告拦截器 功能介绍 Global Speed: 视频速度控制 功能介绍 iTab新标签页(免费ChatGPT) 功能介绍 篡改猴&#xff08;强大的浏览器插件&#xff09; 功能介绍 浏览器下载插件 点击浏览器右上角的三个点&#xff0c;选择扩展 …