数论<1>——数论基础

这期博客是一个数论入门介绍,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;elsecout<<(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.hqwc.cn/news/525393.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

智能革新:2024年AI辅助研发的挑战、机遇与未来展望

引言 在进入2024年的门槛时&#xff0c;我们站在了一个科技飞速发展的新纪元&#xff0c;其中&#xff0c;人工智能&#xff08;AI&#xff09;的持续进步和应用扩展无疑是推动这一变革的强大动力。AI辅助研发&#xff0c;作为将人工智能技术应用于科研和产品开发过程的一种模…

基于yolov5的草莓成长期检测系统,可进行图像目标检测,也可进行视屏和摄像检测(pytorch框架)【python源码+UI界面+功能源码详解】

功能演示&#xff1a; 基于yolov5的草莓成长期检测系统&#xff0c;支持图像检测&#xff0c;视频检测和实时摄像检测功能_哔哩哔哩_bilibili &#xff08;一&#xff09;简介 基于yolov5的草莓成长期检测系统是在pytorch框架下实现的&#xff0c;成长期分为3类&#xff1a;…

介绍下RabbitMQ的事务机制

想要保证发送者一定能把消息发送给RabbitMQ&#xff0c;一种是通过confirm机制&#xff0c;另外一种就是通过事务机制。 RabbitMQ的事务机制&#xff0c;允许生产者将一组操作打包一个原子事务单元&#xff0c;那么全部执行成功&#xff0c;要么全部失败。事务提供了一种确保消…

windows11编译FFmpeg源码完整步骤

1.安装MSYS2 下载并安装MSYS2 安装GCC GCC安装成功 克隆FFmpeg源码 打开MSYS2终端并进入ffmpeg文件夹,然后输入./configure回车开始生成makefile

最少交换次数(求逆序对、树状数组、离散化)

输入样例&#xff1a; 5 9 1 0 5 4 3 1 2 3 0 输出样例&#xff1a; 6 0 解法一&#xff1a;树状数组离散化 #include<iostream> #include<cstring> #include<algorithm> #define int long long using namespace std; const int N5e55; int a[N],b[N],tr[N],…

【Python】新手入门:全局变量和局部变量的概念、区别以及用法

【Python】新手入门&#xff1a;全局变量和局部变量的概念、区别以及用法 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&#x1f448;…

《Python源码剖析》之字符串拼接的一个效率问题

前言 我们常用的字符串拼接方法有两个&#xff0c;一个是通过“”号实现字符串的拼接&#xff0c;还一个就是通过join方法来实现拼接&#xff0c;前者在写法上更加便利&#xff0c;和数字之间的加法运算一样&#xff0c;通常只有两个运算对象&#xff0c;只不过他们的运算规则…

一篇文章带你了解Python数据分析

目录 一、什么是数据分析&#xff1f; 二、为什么学习数据分析&#xff1f; 三、数据分析实现流程 一、什么是数据分析&#xff1f; 是把隐藏在一些看似杂乱无章的数据背后的信息提炼出来&#xff0c;总结出所研究对象的内在规律。 使得数据的价值最大化 指定促销活动的方…

力扣由浅至深 每日一题.01 两数之和

万物惊鸿&#xff0c;唯我澄明 —— 24.3.9 1. 两数之和https://leetcode.cn/problems/two-sum/ 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会…

安全测试工具Burpsuit和OWASP ZAP使用入门指南

Burpsuit使用入门指南 安装&#xff1a; 网上有很多相关相关保姆级别教程&#xff0c;所以这里不加赘述了尽量使用java8版本&#xff0c;破解版兼容8做的比较好如果发现注册机无法打开或者能打开注册机【run】无法点击唤起软件安装&#xff0c;可以使用命令行工具 java -jar …

大模型概念解析 | In-context Learning

注1:本文系"概念解析"系列之一,致力于简洁清晰地解释、辨析复杂而专业的概念。本次辨析的概念是:大模型中的In-context Learning 大模型概念解析 | In-context Learning PR-418: What learning algorithm is in-context learning? Investigations with linear mo…

【力扣白嫖日记】1164.指定日期的产品价格

前言 练习sql语句&#xff0c;所有题目来自于力扣&#xff08;https://leetcode.cn/problemset/database/&#xff09;的免费数据库练习题。 今日题目&#xff1a; 1164.指定日期的铲平价格 表&#xff1a;Products 列名类型product_idintnew_priceintchange_datedate (pr…