信息学竞赛中的数论问题

信息学竞赛中的数论问题

  • by plm

前言

什么是数论?数论到底是什么?
信息学竞赛中的数论主要是整除,同余,互质等方面的问题。
我默认你们已经了解:

  • 模、同余

  • 最大公约数、最小公倍数,注意(k,0)=k

  • 质数、互质

  • 唯一分解定理(抑或是公理?)

提出一个问题

我们让d=(a,b)

,是否存在x,y

,使得ax+by=d

呢?
其实这是可以直接构造一组解的,这里就不多说了,上网搜索“裴蜀定理”即可。

拓展欧几里得算法

现在我们知道x,y

一定是存在的,那么怎样才能将其中一组解求出来呢?暴力枚举?那是O(n)

的,太慢了。
对于方程

ax+by=(a,b)


我们令d=amodb

,且bx+dy=(b,d)

,因为

(a,b)=(b,d)


所以

ax+by=bx+dy


e=[a/b],则有a=eb+d

,所以 

(eb+d)x+by=bx+dy


化简得

b(xyex)=d(xy)


显然我们应该让xyex=0,xy=0,解得 

x=y,y=xey


于是我们可以设计一个函数exgcd(a,b)

,当b=0

时直接出解,否则递归计算gcd(b,amodb)

,得到x,y

,再计算x,y

素数筛法

感觉无聊了?讲点别的吧,比如说素数筛法。
先讲一讲最简单的素数筛法吧。。
弄一个大的数组,ai

是true就代表i是质数,否则是合数,一开始全置为true。然后从2开始(注意不是1)往后扫,每碰到一个质数,假设是i,对于所有的i|j

,把aj

置为false。
时间复杂度是多少呢?筛掉i的倍数的时候,总共要计算ni

次,所以,总的计算次数不超过:

n(1+1/2+1/3+1/4+...+1/n)<=nln(n+1)+c


其中c是一个小常数(欧拉大大得出的结论)。
所以算法的时间复杂度为O(nlog2n)

,不算太慢啦。。最重要的是非常好写

线性素数筛法

“可是我就是想要O(n)

的算法!”——trajan
还有没有可以优化的呢?
每个数好像被筛掉了好几次。
不如这样吧:把任何一个数(包括合数)的素数倍筛掉,假设这个数是i,刚刚把它的j被筛掉,如果j|i

,那么i的倍数就不必筛下去了。
可以证明(略),每个数恰好被筛掉了一次,那么这个算法的时间复杂度为O(n)

,已经是最快的了,而且代码也不算长。

谢谢大家

你可能感兴趣的:(信息学竞赛中的数论问题)