2017.10.29闵神讲课DAY2(tarjan+数论)

2023-10-10 02:59

本文主要是介绍2017.10.29闵神讲课DAY2(tarjan+数论),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

tarjan

割点 割边 强连通分量

tarjan可以求无向图的割点、割边,有向图的强连通分量

求割点割边的方法

首先肯定用暴力枚举点(边)再深搜判断是否连通。
O(n(n+m))或者O(m(n+m))

tarjan算法可以用O(n+m)算出所有的割点割边。

割边

先构建dfs树,先建立dfs序的数组dfn[….]
一条不为割边的条件当且仅当子节点可以通过返祖边访问到比另一个子节点的祖先。
low[….]表示某个点能通过返祖边访问的dfs【】最小的点。
一条边当且仅当low【y】<=dfn[x]时不为割边。

tol=0;
void dfs(int x,edge e)
{dfn[x]=low[x]=++tol;for( x出发的每一条边 且 (x,y)属于E && (y,x )!=e )if( !dfn[y] ) {dfs( y,(x,y) )if( low[y]<low[x] )low[x]=low[y];if( low[y]>dfn[x] ) (y,x)为割边}else{if(dfn[y]<low[x])low[x]=dfn[y];}

割点

割点不一定连着割边
割边连着的不是叶子结点就是割点,但是不一定会连到所有的割点
所以不能通过割边直接得到个割点
和割边类似,low数组定义为不能经过父亲节点能到达的最小dfn值的点。
存在(x,y)使得low[y]>=dfn[x]并且x为根节点时有两个或以上的儿子 那么x就为割点。

PS:如果从2开始存边,那么两条边的异或值=1时这两条边互为反向边

强连通分量

用dfn、low记录。
low将没有任何限制 只要能访问到。就记录
在记录完dfn low后,对于一个点
if(dfn[x]==low[x]) 以x为根节点会形成一堆强连通分量。

itd=0;
void tarjan(int x){dfn[x]=low[x]=++ind;ins[stack[++top]=x]=true;for(int i=head[x].y;i;i=e[i].next)if(!dfn[y=e[i].y]_{tarjan(y);if(low[y]<low[x])low[x]=low[y];}else if(ins[y]&&dfn[y]<low[x])low[x]=dfn[y];if(dfn[x]==low[x]){ int k;tot++;do{k=stack[top--];ins[k]=false;bel[k]=tot;}}}

就可以将一块强连通分量缩为一个点

数论

模运算

加减乘除模运算

单位元 逆元

加法单位元:0
乘法单位元:1
x* y%p=1→x* y=z* p+1→x* y-z*p=1
所以我们可以把这个式子写成 a* x+b* p=1(道理是一样的) 其中a和b是整数
像这样 可以被表示成上面ax+bp形式的数的集合被称为x和p的线性组合
定理:gcd(x,y)是x和y的线性组合中的最小正整数。
那么一个数属于x和p的线性组合当且仅当它被gcd(x,p)整除,也就是说x有逆元当且仅当xp互质

ps:那么 我们就可以解决一个很玄学的问题了,为什么很多题目都让我们对一个非常大的质数取模而不是一个非常大的任意数,如果是一个非常大的合数,那么很多数字就没有乘法逆元,在除法计算的时候就会遇到很多不必要的麻烦。那么有些题目它要模的质数会在输入里面出现,那可能就会导致这个模数不为质数,也就是不能进行除法运算。

欧几里得算法

gcd(a,b)=gcd(a,b-a)
gcd(a,b)=gcd(b,a)
gcd(a,0)=a
易推出gcd(a,b)=gcd(a,b%a)
这个求最大公约数算法的时间复杂度是O(logn)的(因为b%a<1/2b)最坏情况下为这两个数字为斐波那契数列中连续的两个数(显然法证明23333)

扩展欧几里得算法

模运算不能有分数了,但是x依然有变成1的可能
x* y%p=1→x* y=z* p+1→x* y-z* p=1。
也就是说除以x我们只需要找到x乘谁等于1然后乘以这个数就行了,但是怎么去找这个数?
看上面那个式子,因为z是整数,所以我们可以把式子写成a*x+b*p=1,其中a和b是整数。
像这样 可以被表示成上面ax+bp形式的数的集合被称为x和p的线性组合。
定理:gcd(x,y)是x和y的线性组合中的最小正整数。
那么一个数属于x和p的线性组合当且仅当它被gcd(x,p)整除,也就是说x有逆元当且仅当xp互质
设xa+yb=d=gcd(a,b),其中x和y可能有很多对,我们的任务就是求出至少一对x和y。
根据欧几里得算法,xa+yb=d=x’(b)+y’(a%b)
最后一定有x’=1,y’=0,那么我们只需要在递归返回的时候通过x’和y’计算出x和y就行了。
a%b=a-a/b* b,那么d=y’a-(x’-a/b* y’)*b(/为整除)
待定系数就能求出x=y’,y=x’-a/b*y’。
大功告成,递归求gcd返回的同时递推一下就行
“为了让你们不觉得这玩意很恐怖我压一下码。”

这里写图片描述
然后求出来这个x之后你把它fix一下就可以辣。
当然还有一个迭代版本的,效率可能更高一些,但是我还没有理解代码,如果想学可以找你们学姐要。时间复杂度都是O(log(min(n,p)))不给证明

欧拉定理

》》欧拉函数
若x和p互质,则x^euler(p) ≡1(mod p),其中euler(p)是比p小且与p互质的数的个数,称为欧拉函数。
于是乎x^(euler(p)-1)就是x的逆元了。
于是我们可以用倍增快速幂来求。
时间复杂度为O(logp),但是logp同时也是下界,所以可能会比扩欧慢一些,但是写起来方便.

LUCAS定理

例题:

要求:p为质数

C(n,m)%p=C(n/p,m/p)*C(n%p,m%p)(p为质数)
要背下来!

ll C( ll n,ll m)
{
return n<=p&&m<=p? C[n][m] : C[n%p][m%p]*C()
}

证明:以2进制为例,假如以二进制输入,那么我们可以发现:它就是把每一位拆开,从最低为开始求组合数,将其余位继续递归。
O(p^2+logn)
例题:BZOJ4591

中国剩余定理

只在模数的所有因子都互质的情况下才是

若我们已知m个互不相同的模数pi(i=1…m)那么一个数模这几个数的余数(a1,a2,…,am)与这个数模这m个数P的乘积r存在一一对应关系。
设Mi=P/pi(整除),ti=Mi^-1(mod pi),那么
r=sum{ai*ti*Mi}%P
有了这个式子,我们就可以分别求出来答案模P的质因子的结果然后用这个式子将最终答案还原即可。

欧拉筛(线性筛)

我们介绍一种叫做欧拉筛的筛法,他能够通过独特的“每个合数会被不重不漏”地筛一遍的方法达到O(n)的效率,因此也称为线性筛。
这里写图片描述

BSGS

问题:求满足a^x≡y(mod p)的最小的x,ap互质。
设x=im+j(0≤j<m)
那么a^(im)≡y*a^(-j)(mod p)
枚举j,将所有的y*a^(-j)放入哈希表中。
然后枚举i,在哈希表中查找a^(-im)是否存在。
第一个匹配的im+j是最小解(因为从小到大枚举i)。
BSGS是一个叫做meet-in-the-middle算法的实例。

PS:课后老刘案例的网上求逆元的玄学方法:

1、费马小定理(自行度娘)
2、递推法
这里写图片描述

非常神奇的O(n)算法,很实用。

这篇关于2017.10.29闵神讲课DAY2(tarjan+数论)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/177457

相关文章

JDK9到JDK21中值得掌握的29个实用特性分享

《JDK9到JDK21中值得掌握的29个实用特性分享》Java的演进节奏从JDK9开始显著加快,每半年一个新版本的发布节奏为Java带来了大量的新特性,本文整理了29个JDK9到JDK21中值得掌握的... 目录JDK 9 模块化与API增强1. 集合工厂方法:一行代码创建不可变集合2. 私有接口方法:接口

数论入门整理(updating)

一、gcd lcm 基础中的基础,一般用来处理计算第一步什么的,分数化简之类。 LL gcd(LL a, LL b) { return b ? gcd(b, a % b) : a; } <pre name="code" class="cpp">LL lcm(LL a, LL b){LL c = gcd(a, b);return a / c * b;} 例题:

数论ZOJ 2562

题意:给定一个数N,求小于等于N的所有数当中,约数最多的一个数,如果存在多个这样的数,输出其中最大的一个。 分析:反素数定义:对于任何正整数x,其约数的个数记做g(x).例如g(1)=1,g(6)=4.如果某个正整数x满足:对于任意i(0<i<x),都有g(i)<g(x),则称x为反素数。 性质一:一个反素数的质因子必然是从2开始连续的质数。 性质二:p=2^t1*3^t2*5^t3*7

POJ2247数论

p = 2^a*3^b*5^c*7^d 求形如上式的第n小的数。 import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;import java.math.BigInteger;import java.u

CSP-J基础之数学基础 初等数论 一篇搞懂(一)

文章目录 前言声明初等数论是什么初等数论历史1. **古代时期**2. **中世纪时期**3. **文艺复兴与近代**4. **现代时期** 整数的整除性约数什么样的整数除什么样的整数才能得到整数?条件:举例说明:一般化: 判断两个数能否被整除 因数与倍数质数与复合数使用开根号法判定质数哥德巴赫猜想最大公因数与辗转相除法计算最大公因数的常用方法:举几个例子:例子 1: 计算 12 和 18

CSP-J基础之数学基础 初等数论 一篇搞懂(二)

文章目录 前言算术基本定理简介什么是质数?举个简单例子:重要的结论:算术基本定理公式解释:举例: 算术基本定理的求法如何找出质因数:举个简单的例子: 重要的步骤:C++实现 同余举个例子:同余的性质简介1. 同余的自反性2. 同余的对称性3. 同余的传递性4. 同余的加法性质5. 同余的乘法性质 推论 总结 前言 在计算机科学和数学中,初等数论是一个重要的基础领域,涉及到整数

Java预备知识 - day2

1.IDEA的简单使用与介绍 1.1 IDEA的项目工程介绍 Day2_0904:项目名称 E:\0_code\Day2_0904:表示当前项目所在路径 .idea:idea软件自动生成的文件夹,最好不要动 src:src==sourse→源,我们的源代码就放在这个文件夹之内 Day2_0904.iml:也是自动生成的文件,不要动 External Libraries:外部库 我这

2014年暑假培训 - 数论

A银河上的星星 /**************************************************************     Problem: 1014     User: DoubleQ     Language: C++     Result: Accepted     Time:190 ms     Memor

ZOJ1007(数论)

题目链接:点击打开链接 解题思路:   纯粹的数学题,没有输入,直接要求输出.直接给出的求和式子极限到无穷,无法直接计算.Hint里给出了提示,大意就是说求g(x) - g(1)的求和极限,最后再加上g(1)就能求出g(x).   由g(x)  - g(1) 能够得出 1 / k*(k+x) - 1 / k * (k + 1) = (1 - x) / k * ( k + 1) * (k

基于Python的机器学习系列(29):前馈神经网络

在本篇文章中,我们将学习如何使用PyTorch构建和训练一个前馈神经网络。我们将以线性回归为例,逐步了解PyTorch的各个组件及其在神经网络中的应用。这些步骤包括: 指定输入和目标:我们将定义输入特征和目标变量。数据集和数据加载器:使用PyTorch的数据集和数据加载器来管理和加载数据。nn.Linear(全连接层):创建前馈神经网络中的线性层。定义损失函数:选择合适的损失函数