算法竞赛——数论(一),数论内容的介绍,基础数论

news2024/10/6 0:26:55

文章目录

        • 一, 数论学习路线的介绍和相关建议
          • 1,建议学习人群 :
          • 2,建议学习时长
          • 3,学习路线的介绍
            • 1,基础数论
            • 2,组合数学
            • 3,计算几何
        • 二,基础数论第一部分 —— 快速幂和快速幂矩阵
          • 1,快速幂
            • 1,解题背景
            • 2,思想
            • 3,代码
        • (扩展)矩阵的计算
          • 2,矩阵的快速幂
          • (矩阵)矩阵加速
          • 3,课后例题
            • 1,快速幂专区
            • 2,快速幂矩阵专区

本文在撰写的时候出现了一些小问题,在第一次撰写时没有注意笔记本电量导致直接关机丢失上千字长文 /哭脸/,在此特别提醒大家在学习或者时使用电脑进行生产力活动的时候要及时保存文件🐂。

本文是数论的开篇之章,会有相关数论学习方法和路线的推荐,大家可以借鉴相关思路,下面我们会一点一点进入数论的学习,希望大家能坚持住数论板块的学习,一定会学有所得的!

在这里插入图片描述



慢也好,步子小也好,是在往前走就好。


一, 数论学习路线的介绍和相关建议

本专栏的内容为算法竞赛中的数论内容,来自笔者自身的一些小见解仅作参考,特殊情况应特殊看待。

1,建议学习人群 :

目标赛事奖项为 ICPC区域赛 / 蓝桥杯国赛二等奖以上 / 河北省赛 二等奖以上 ,有一定算法基础并感兴趣的同学(至少要了解一些基础算法)


2,建议学习时长

本专题将会分成四个大部分,建议每一个大部分耗时不要超过20天,总学习时长控制在三个月以内。


3,学习路线的介绍

如下图所示,我们把数论的学习分成了四个板块,由于基础数论的内容非常多,所以在分类的时候我们把基础数论分成了两个板块,分开学习效率更能最大化。

我们在学习数论的前期的时候可以选择性的选择考点比较集中的地方先学习,这样的学习路径可以极大的提高我们的算法实现能力,可以极大的提高我们算法学习的积极性,重点内容 :数论第一阶段,计算几何和组合数学基础内容,按照整个进度学习,虽然体系不完整,但是确实能带来效益的最大化!

当然也可以按照知识体系的顺序学习,这样学习方式比较适合队内的专业数论手,大家可以按照自身的进度调整数论学习路线,下面我们详细的分部分介绍一下所要设计的知识

1,基础数论

首先我们会介绍一下什么是质数,约数,最大公因数… 一些数学定义,在数学中的相关定义和一些取模的技巧的介绍,然后我们就会正式的进入到基础数论的学习中来了,首先是算法竞赛中的快速幂,这个算法结构在算法竞赛中主要用来对一些迭代的程序进行加速的操作!然后我们会介绍一下简单的 GCD和LCM 算法的实现流程,还有素数的筛选,欧拉函数的识别和使用。

第二部分我们主要学习的内容都是和数学中的比较偏门的定理,这块的性价比并不能算的上高,所以这部分的内容可以选择性的跳过,我们只要知道有这个定理,在看题的时候有这么个思路就好,当我们知道这个思路来自数论之后再拿出我们的板子,一般这种题型比较喜欢出现防AK的HANK题中,程度比较弱的同学可以直接跳过。

2,组合数学

组合数学就是我们高中数学中学到的排序和组合问题,只不过会更加的专业,更加的代码化,这部分的内容我认为是比较简单的,尤其是这部分前面的内容,基本就是对高中知识点的复习,这部分题目在贪心题中出现的非常严重,练习这部分的知识,以后就能成为队内的贪心大王,后面的小定理还是了解思路即可,我们目前最主要的方向还是去学习一些简单的知识体系,没有必要去冲击过于困难的内容,毕竟有时候思路出来了,代码手也搓不出来代码

3,计算几何

计算几何整体的难度比较平均,都是中等难度的知识点,建议大家都了解一下,这个对我们对多维图形的模拟很重要,可能会卡在铜牌题的位置,对这部分还是要注意,相关的板子即使背不过,赛时也要带上,我的建议时全部都要了解学习,如果实在是时间有限,可以放弃三维几何部分。

二,基础数论第一部分 —— 快速幂和快速幂矩阵
1,快速幂
1,解题背景

在一般运算中我们可以用循环的方式来求解Nk,但是当这个 K 的数据范围超过 109,以后使用循环求解就显的比较无力了,为了给循环提提速,我们提出了快速幂的思想!

2,思想

快速幂实际上就是使用了二进制的思想进行实现,迭代乘法的方式来实现

3,代码

下面是求解 an 的二次幂代码

typedef long long LL ;
/*
    函数一: fastPow(参数1:表示幂的底数 , 参数2:表示幂的指数 )  
    //  注意数据类型

    函数二 : fastPow(参数1:表示幂的底数 , 参数2:表示幂的指数 , 参数3 : 取模数)
*/
LL fastPow(int a ,int n){
    LL ans = 0 ;
    while(n){
        if(n&1)ans*=a;
        a*=a; n >>= 1 ;
    }
    return ans ; 
}

LL fastPow(LL a ,LL n , LL mod){
    LL ans = 0 ;
    while(n){
        if(n&1) ans*=a,ans%=mod;
        a%=mod,a*=a,a%=mod;
        n>>=1;
    }
    return ans ; 
}

时间复杂度: O(logN)


(扩展)矩阵的计算

在完成了快速幂的讲解之后我们想到了一个问题,这种乘法是知道一个固定的系数的,但是当我们面对更加复杂的矩阵的时候我们应该如何应对?就比如斐波那契数列这种相加关系 An+1 = An + An-1

这叫要使用我们下面的矩阵,为了保护一些没有学线性代数的同学,我们将介绍一些矩阵中简单的规则。


矩阵的加法 : 对应位置直接加减

矩阵的乘法 : 第一个矩阵的第 i 行乘以第二个矩阵的第 j 列,可以得到 Di , j


2,矩阵的快速幂

**思想:**快速幂的思想 + 矩阵的乘法 + 矩阵的结合律

代码:

matrix operator * ( const matrix &a , const matrix &b ){
	matrix c ; 
	memset(c.m,0,sizeof c.m);
	for(int i = 0 ; i < N ; i ++ ){
		for(int j = 0 ; j < N ; j ++ ){
			for(int k = 0 ; k < N ; k ++ ){
				c.m[i][j] = (a.m[i][k] + c.m[i][j] + b.m[k][j]) % mod ; 
			}
		}
	}
	return c ; 
}

matrix pow_matrix(matrix a , int n ){
	matrix ans; 
	memset(ans.m,0,sizeof ans.m);
	for(int i = 0 ; i < N ; i ++ ) ans.m[i][i] = 1 ; 
	while(n){
		if(n&1) ans = ans * a;
		a = a * a ; 
		n >>= 1 ;  
	}
	return ans ; 
}

实际应用 :

  • 斐波那契数列 : 使用矩阵快速幂进行乘法的快速递推能迅速的降低时间复杂度 (本次解题一定要有相关的题解来着重的解释学习的知识占比)
  • 所有多项式中但是有系数关系的知关系都可以使用这种方式尝试实现!

1,计算走 K 次能达到的位置 ,使用 1 / 0 法来进行表示

2,计算走 K 次到达每个点的距离长度

相关的代码可以沿用上文的矩阵中的二次幂来解决问题


(矩阵)矩阵加速

在矩阵中很多的高级用法实际上我们是没有做出相关的解释的,本质上是为了快速幂的知点我们能学习的更加的细致,下面我们来解决的问题是矩阵学习中会涉及到的相关问题,我们学习这部分内容能让我们对矩阵加速有更加详细的认识,相比较而言这部分的定理内容对于有线性代数同学还是比较优待的,话不多说先进入正题:

矩阵加速——矩阵快速幂最常用的算法

矩阵加速算法是一种基于矩阵运算的优化方法,主要用于提高计算效率。矩阵快速幂算法是一种用于高效计算矩阵的高次方的算法。它将朴素的时间复杂度O(n)降到了log(n),从而大大提高了计算效率。

该算法的基本原理是将n个矩阵进行两两分组,然后将每组中的矩阵进行乘法运算,从而得到矩阵的n次方。通过利用矩阵乘法的结合律,可以减少重复计算的次数,进一步提高计算效率。具体实现中,可以将幂次转化为二进制形式,然后根据二进制位进行矩阵的分组和乘法运算。这样可以进一步减少计算量,提高计算效率。

简单的来说矩阵快速幂的原理就是,快速幂思想,矩阵乘法只跟左右顺序有关,和先计算那一部分无关,使用这个原理我们在推导相关的递推公式就可以在我们的矩阵快速幂模板中实现矩阵加速的操作。


3,课后例题
1,快速幂专区

P1226 【模板】快速幂

在这里插入图片描述

题目类型 : 模板题

过题代码:

代码一

#include <iostream>
using namespace std ;
typedef long long LL ;
int main () {
	LL a , b , p ;
	cin >> a >> b >> p ;
	LL c = 1 ; 
	LL aa = a ; 
	LL bb = b ; 
	while(b){
		if(b&1){
			c %= p ;
			c *= a ; 
			c %= p ;
		}
		a %= p ;
		a *= a ;
		a %= p;
		b >>= 1 ;
	}
	cout << aa << "^" << bb << " mod " << p << "=" << c << endl ;
	return 0 ;	
}

代码二

#include <iostream>
using namespace std ;
typedef long long LL ;

LL fastpow(LL a , LL b , LL mod ){
	LL c = 1 ;
	while(b){
		if(b&1){
			c *= a ;
			c %= mod ; 
		}
		b >>= 1 ;
		a %=mod ;
		a *= a ;
		a %=mod;  
	}
	return c ; 
}

int main (){
	LL a , b , c ;
	cin >> a >> b >> c ;
	cout << a << "^" << b << " mod " << c << "=" << fastpow(a,b,c)<< endl;
	return 0 ;
}

快速幂部分的题型一般都是纯粹的板子题,非常的明显,就不过多的扩展介绍了

2,快速幂矩阵专区

快速幂矩阵有一道模板题,我给大家整理出了来,相关的快速幂矩阵的大量的知识为了体现快速幂的思想我们都没有详细的体现,完成这道题目之后我们将会更加详细的介绍

【模板】矩阵快速幂

题目描述

给定 n × n n\times n n×n 的矩阵 A A A,求 A k A^k Ak

输入格式

第一行两个整数 n , k n,k n,k
接下来 n n n 行,每行 n n n 个整数,第 i i i 行的第 j j j 的数表示 A i , j A_{i,j} Ai,j

输出格式

输出 A k A^k Ak

n n n 行,每行 n n n 个数,第 i i i 行第 j j j 个数表示 ( A k ) i , j (A^k)_{i,j} (Ak)i,j,每个元素对 1 0 9 + 7 10^9+7 109+7 取模。

样例 #1

样例输入 #1

2 1
1 1
1 1

样例输出 #1

1 1
1 1

提示

【数据范围】

对于 100 % 100\% 100% 的数据, 1 ≤ n ≤ 100 1\le n \le 100 1n100 0 ≤ k ≤ 1 0 12 0 \le k \le 10^{12} 0k1012 ∣ A i , j ∣ ≤ 1000 |A_{i,j}| \le 1000 Ai,j1000


解题代码

#include <iostream>
#include <cstring>
using namespace std ;
const int N = 110 ;
const int mod = 1e9 + 7 ;    
typedef long long LL ; 
struct matrix {
	LL m[N][N] ; 
};
matrix operator * (const matrix &a , const matrix &b ){
	matrix c ; 
	memset(c.m , 0 , sizeof c.m );
	for(int i = 0 ; i < N ; i ++ ){
		for(int j = 0 ; j < N ; j ++ ){
			for(int k = 0 ; k < N ; k ++ ){
				c.m[i][j] += ((a.m[i][k] % mod) *( b.m[k][j] % mod) %mod); 
				c.m[i][j] %= mod ; 
			}
		}
	}
	return c ; 
} 

matrix pow_matrix ( matrix a , LL b ){
	matrix c ; 
	memset(c.m , 0 , sizeof c.m ) ;
	for(int i = 0 ; i < N ; i ++ ) c.m[i][i] = 1 ; 
	while(b){
		if(b&1){
			c = c * a ;
		}
		a = a * a ; 
		b >>= 1 ; 
	} 
	return c ; 
}

int main () {

	LL n , k ;
	cin >> n >> k ;
	matrix c ; 
	for(int i = 0 ; i < n ; i ++ ){
		for(int j = 0 ; j < n ; j ++ ){
			cin >> c.m[i][j] ; 
		}
	}
	matrix d = pow_matrix(c , k);
	for(int i = 0 ; i < n ; i ++ ){
		for(int j = 0 ; j < n ; j ++ ){
			cout << d.m[i][j] << ' '; 
		}
		cout << endl ;
	}
	return 0 ; 
}

**Div 2 改装题 **

矩阵加速(数列)

题目描述

已知一个数列 a a a,它满足:

a x = { 1 x ∈ { 1 , 2 , 3 } a x − 1 + a x − 3 x ≥ 4 a_x= \begin{cases} 1 & x \in\{1,2,3\}\\ a_{x-1}+a_{x-3} & x \geq 4 \end{cases} ax={1ax1+ax3x{1,2,3}x4

a a a 数列的第 n n n 项对 1 0 9 + 7 10^9+7 109+7 取余的值。

输入格式

第一行一个整数 T T T,表示询问个数。

以下 T T T 行,每行一个正整数 n n n

输出格式

每行输出一个非负整数表示答案。

样例输入 #1

3
6
8
10

样例输出 #1

4
9
19

提示

  • 对于 30 % 30\% 30% 的数据 n ≤ 100 n \leq 100 n100
  • 对于 60 % 60\% 60% 的数据 n ≤ 2 × 1 0 7 n \leq2 \times 10^7 n2×107
  • 对于 100 % 100\% 100% 的数据 1 ≤ T ≤ 100 1 \leq T \leq 100 1T100 1 ≤ n ≤ 2 × 1 0 9 1 \leq n \leq 2 \times 10^9 1n2×109

过题代码

#include <iostream>
#include <cstring>
using namespace std ;
const int N = 5 ;
const int mod = 1e9 + 7 ;    
typedef long long LL ; 
struct matrix {
	LL m[N][N] ; 
};
matrix operator * (const matrix &a , const matrix &b ){
	matrix c ; 
	memset(c.m , 0 , sizeof c.m );
	for(int i = 0 ; i < N ; i ++ ){
		for(int j = 0 ; j < N ; j ++ ){
			for(int k = 0 ; k < N ; k ++ ){
				c.m[i][j] += ((a.m[i][k] % mod) *( b.m[k][j] % mod) %mod); 
				c.m[i][j] %= mod ; 
			}
		}
	}
	return c ; 
} 

matrix pow_matrix ( matrix a , LL b ){
	matrix c ; 
	memset(c.m , 0 , sizeof c.m ) ;
	for(int i = 0 ; i < N ; i ++ ) c.m[i][i] = 1 ; 
	while(b){
		if(b&1){
			c = c * a ;
		}
		a = a * a ; 
		b >>= 1 ; 
	} 
	return c ; 
}
int main () {

	LL n  ;
	cin >> n ;
	matrix c ;
	memset(c.m,0, sizeof c.m);
	c.m[0][0] = 1 ;
	c.m[0][1] = 1 ;
	c.m[0][2] = 1 ;
	matrix a ; 
	memset(a.m,0,sizeof a.m);
	a.m[0][1] = 1 ; 
	a.m[1][2] = 1 ; 
	a.m[2][0] = 1 ; 
	a.m[2][2] = 1 ; 
	while(n--){
		LL k ; 
		cin >> k ;
		if(k==1||k==2){
			cout << 1 << endl ;
			continue ;
		}
		k -= 3 ;

		matrix d = pow_matrix(a,k);
		matrix e = c * d ; 
		cout << e.m[0][2] << endl ; 

	}

	return 0 ; 
}

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

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

相关文章

2023年十大最佳 iPhone 恢复软件

您的 iPhone 存储了大量有价值的数据&#xff0c;包括照片和视频。但是&#xff0c;即使使用高度安全的 Apple 设备&#xff0c;数据丢失也可能随时发生。从众多可用工具中选择最适合 iPhone 的数据恢复软件可能是一项艰巨的任务。因此&#xff0c;我们测试了性能并审查了 2023…

使用Hypothesis生成测试数据

&#x1f4e2;专注于分享软件测试干货内容&#xff0c;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;交流讨论&#xff1a;欢迎加入我们一起学习&#xff01;&#x1f4e2;资源分享&#xff1a;耗时200小时精选的「软件测试」资…

[vue-router]vue3.x Hash路由前缀问题

[vue-router]vue3.x Hash路由前缀问题 问题描述问题分析 问题描述 是在本地开发时&#xff0c;使用的HASH路由&#xff0c;然后在偶然的情况下在/#/前添加了前缀&#xff0c;发现不影响本地的路由的使用&#xff1f;&#xff1f;&#xff1f;&#xff01;&#xff01;&#xf…

rviz中引入SW的模型

一、SW装配图转urdf 参考链接&#xff1a;https://blog.csdn.net/weixin_45168199/article/details/105755388 这部分直接看参考链接就可以&#xff0c;主要思路如下 1、把sw中的零散零件按照机器人中连杆的分类整合成几个大零件 2、把几个大零件整合成装配体&#xff0c;并…

如何在Jetpack Compose中显示PDF?

当读取和显示 PDF 的组件缺失时该怎么办? 声明式编程可以拯救你. Jetpack Compose已经存在好几年了, 但_在某些方面它的使用仍然面临挑战_. 例如, 缺少用于查看PDF的官方组件, 而为数不多的第三方库通常也是有代价的. 在我们的应用中, 我们会遇到在许多场景中显示 PDF 的需求…

跨境电商源码独立开发:一次购买,终生使用

随着全球电子商务的快速发展&#xff0c;越来越多的企业开始涉足跨境电商领域。为了在这个竞争激烈的市场中脱颖而出&#xff0c;您需要一个专业的跨境电商解决方案。我们的团队为您提供最优质的源码独立开发服务&#xff0c;让您拥有一个功能强大、安全稳定的跨境电商平台。 一…

腾讯觅影数智医疗影像平台获颁世界互联网领先科技成果大奖

11月8日&#xff0c;2023年世界互联网大会乌镇峰会在乌镇举行&#xff0c;腾讯再度获颁“世界互联网领先科技成果”大奖。腾讯健康总裁吴文达在世界互联网领先科技成果发布活动中介绍&#xff0c;“腾讯觅影数智医疗影像平台”已全面开放20多个医疗AI引擎助力科研创新&#xff…

2007-2022年全国各地级市金融机构网点数据

2007-2022年地级市金融机构网点数据 1、时间&#xff1a;2007-2022年 2、指标&#xff1a;行政区划代码、年份、城市名称、所属省份、银行网点数量、其中-政策性银行及国家开发银行营业网点占比、其中-商业银行营业网点数量占比、其中-农村金融机构营业网点数量占比 3、范围…

P3379 【模板】最近公共祖先(LCA)

洛谷里面8页题解千篇一律&#xff0c;就没有用线段树求解的&#xff0c;这下不得不由本蒟蒻来生啃又臭又硬&#xff0c;代码又多的线段树了。 样例的欧拉序列&#xff1a;4 2 4 1 3 1 5 1 4 记录每个节点最早在欧拉序列中的时间&#xff0c;任意两个节点的LCA就是他们两个节点…

Python 实现动态动画心形图

在抖音上刷到其他人用 matlab 实现的一个动态心形图&#xff0c;就想也用 Python 实现&#xff0c;摸索了两种实现方式&#xff0c;效果如下&#xff1a; 方法一&#xff1a; 利用循环&#xff0c;结合 pyplot 的 pause 与 clf 参数实现图像的动态刷新 import matplotlib.p…

MATLAB绘图中文显示为方框

MATLAB绘图中文显示为方框 MATLAB显示英文和字母没有问题&#xff0c;但是当显示中文时会显示乱码&#xff0c;中文显示为方框&#xff0c;如下图&#xff1a; 可以在绘图命令中添加如下代码&#xff1a; set(gca,Fontname,Monospaced); 例如&#xff1a; % 滤波器系数%低通…

Kafka入门

kafka无疑是当今互联网公司使用最广泛的分布式实时消息流系统&#xff0c;它的高吞吐量&#xff0c;高可靠等特点为并发下的大批量实时请求处理提供了可靠保障。很多同学在项目中都用到过kafka&#xff0c;但是对kafka的设计原理以及处理机制并不是十分清楚。为了知其然知其所以…

vue项目代码防止被调试-打开控制台直接跳空白页面

vue项目代码防止被调试-打开控制台直接跳空白页面 前端代码上线后&#xff0c;代码会暴露&#xff0c;或者接口暴露&#xff0c;会被有心之人研究代码逻辑&#xff0c;找到项目bug漏洞&#xff01; 项目背景 被安全测试针对了&#xff0c;总是调试我这不太安全的代码。前端代码…

用dbeaver创建一个enum类型,并讲述一部分,mysql的enum类型的知识

写这个博客的目的就是我在网上看了半天&#xff0c;发现没有这方面的知识&#xff0c;也许是老手认为这个太简单了&#xff0c;不过我还是告诉新人使用dbeaver来创建一个enum类型的方法&#xff1a; 就是enum("a","b","name") 第一步用dbeaver…

搜索引擎Elasticsearch基础与实践

倒排索引 将文档中的内容分词&#xff0c;然后形成词条。记录每条词条与数据的唯一表示如id的对应关系&#xff0c;形成的产物就是倒排索引&#xff0c;如下图&#xff1a; ElasticSearch数据的存储和搜索原理 这里的索引库相当于mysql中的database。一个文档&#xff08;do…

大语言模型(LLM)综述(七):大语言模型设计应用与未来方向

A Survey of Large Language Models 前言8 A PRACTICAL GUIDEBOOK OF PROMPT DESIGN8.1 提示创建8.2 结果与分析 9 APPLICATIONS10 CONCLUSION AND FUTURE DIRECTIONS 前言 随着人工智能和机器学习领域的迅速发展&#xff0c;语言模型已经从简单的词袋模型&#xff08;Bag-of-…

Mabitys总结

一、ORM ORM(Object/Relation Mapping)&#xff0c;中文名称&#xff1a;对象/关系 映射。是一种解决数据库发展和面向对象编程语言发展不匹配问题而出现的技术。 使用JDBC技术时&#xff0c;手动实现ORM映射&#xff1a; 使用ORM时&#xff0c;自动关系映射&#xff1a; &am…

【JavaEE】HTTP协议(什么是HTTP?、HTTP格式、form表单和ajax构造HTTP)

一、什么是HTTP协议&#xff1f; 1.1 HTTP (全称为 “超文本传输协议”) 是一种应用非常广泛的 应用层协议 1.2 理解HTTP协议的工作过程 当我们在浏览器中输入一个 “网址”, 此时浏览器就会给对应的服务器发送一个 HTTP 请求. 对方服务器收到这个请求之后, 经过计算处理, 就…

FMCW雷达论文速览 | TRS 2023, 基于FMCW雷达的多天线高精度测距算法及性能分析

注1:本文系“最新论文速览”系列之一,致力于简洁清晰地介绍、解读最新的顶会/顶刊论文 TRS 2023 | High Accuracy Multi-antenna Ranging Algorithm and Performance Analysis for FMCW Radar 论文原文:https://ieeexplore.ieee.org/document/10309162 Z. Xu, S. Qi and P. Zh…

Python教程之Python中文件路径

文章目录 前言一、Python中文件路径1.绝对路径和相对路径2.目录中的斜杠们3.正则表达式中的斜杠们 二、什么是文件路径&#xff0c;Python中如何书写文件路径&#xff1f;1.Windows上的反斜杠以及OS X和Linux上的正斜杠关于Python技术储备一、Python所有方向的学习路线二、Pyth…