数论知识
数论的知识与信息学竞赛关系密切相关,尤其是初等数论。初等数论是用初等数学方法来研究整数的整除、同余式等方面问题的数论分支。其内容包括辗转相除法、进位制、因数、倍数、公因数、公倍数、最大公因数、最小公倍数、素数、合数等。
一、素数与整除问题
1、素数和合数
大于1的正整数p,如果p仅有的正因子是1和p,则称p为素数;大于1且不是素数的正整数称为合数。如果n是合数,则必有一个小于等于的素因子。
2、整数和约数
如果a和b是整数,若有整数c使b=ac,就说a整除b。在a整除b时,记a是b的一个因子(约数),b是a的倍数。符号a|b表示a整除b。整数可整除性的基本性质有:
①若a|b,a|c,则a|(b+c);
②若a|b,那么对所有整数c有a|bc;
③若a|b,b|c,则a|c;即整数整除具有传递性。
3、素数的求法
例1 求2~n之间的素数。
方法一 根据素数的定义我们给出它的算法:
for i:=2 to n do
begin
1. 用2到去除i,看能否除尽
flag:=true
for j:=2 to round(sqrt(i))
if i mod j=0 then flag:=false
2.if 除不尽 then 输出素数i。
参考程序
var n,i,j,count:integer;
flag:boolean;
begin
write(‘input n:’);
readln(n);
count:=0;
for i:=2 to n do
begin
flag:=true;
for j:=2 to round(sqrt(i)) do
if i mod j=0 then flag:=false;
if flag
then begin
write(i,′ ′);
count:=count+1;
if count mod 5=0 then writeln;
end;
end;
end.
方法二 用筛选法求素数,算法如下:
1.建立[2..n]的集合
2.repeat
找出当前集合中的最小数(即素数)
打印该最小数
从集合中减去该素数的所有倍数
UNTIL集合为空
参考程序
const maxn=10000;
var
sieve:set of 1..maxn;
next,mul,n:integer;
begin
readln(n);
sieve:=[2..n];
next:=2;
repeat
while not(next in sieve) do
next:=next+1;
write(next:3);
mul:=next;
while mul<=n do
begin
sieve:=sieve-[mul];
mul:=mul+next;
end;
until sieve=[ ];
end.
二、最大公约数和辗转相除法、最小公倍数
1、除法的定义和同余
令a为整数,d正整数,那么有惟一的整数q和r,其中0≤r<d,使得a=bq+r。可以用这个定理来定义除法:d叫除数,a叫被除数,q叫商,r叫余数。如果两个数a,b除以一个数c的余数相等,则说a和b关于模c同余,记作a≡b(mod c)。
2、最大公约数和最小公倍数
令a和b是不全为0的两个整数,能使d|a和d|b的最大整数称为a和b的最大公约数,用gcd(a,b)表示。令a和b是不全为0的两个整数,能使a|d和b|d的最小整数称为a和b的最小公倍数,用lcm(a,b)表示。令a和b为正整数,则有ab=gcd(a,b)×lcm(a,b)。
3、辗转相除法
用辗转相除法求最大公约数:利用gcd(a,b)=gcd(b,a mod b)(a>b)进行迭代,算法如下:
function gcd(a,b:longint):longint;
begin
if b=0 then gcd:=a
else gcd:=gcd(b,a mod b);
end;
例2 最大公约数与最小公倍数问题。
输入二个正整数x0,y0(2≤x0<100000,2≤y0≤1000000),求出满足下列条件的p,q的个数:
①p,q是正整数;②要求p,q以x0为最大公约数,以y0为最小公倍数。
试求:满足条件的所有可能的两个正整数的个数。
算法分析
⑴如何判别两个自然数素质
x和y的最大公约数为gcd(x,y)=
function gcd(x,y:longint):longint;
begin
if y=0 then gcd:=x
else gcd:=gcd(y,x mod y);
end;{gcd}
显然,gcd(x,y)=1是x与y互质的标志。除1以外的任何自然数n都可以惟一的分解成质数的乘积:
n=p1l1*p2l2*…*pklk是(质数p1<p2<…<pk,质数的次幂l1,l2,…,lk>0)
⑵如何计算以x0为最大公约数,以y0为最小公倍数的(p,q)个数
明确几个问题:
①若y0不能整除x0,则不存在以x0为最大公约数、以y0为最小公倍数的(p,q);
②若x0=y0,则p=q=x0=y0,即满足条件的p和q仅为一对(x0,y0);
③若x0≠y0且y0整除x0,则满足条件的p和q一定为偶数对。
设=n=1*p1l1*p2l2*…*pklk
若分解出k个质数的乘积的话,则满足条件的p和q的个数有:
tot:=0; {tot为记录满足条件的(p、q)个数}
if y0 mod x0=0 {若y0不能整除x0,则不存在满足条件的(p,q)}
then begin
y:=y0 div x0;
{计算=n=1* p1l1*p2l2*…*pklk,确定满足条件的p和q的个数有 }
for i:=1 to trunc(sqrt(y)) do
if (y mod i=0) and (gcd(i,y div i)=1) then inc(tot,2);
if y=1 then dec(tot); {若x0=y0,则(x0,y0)即为满足条件的(p,q)}
end;{then}
输出满足条件的(p,q)个数tot。
参考程序:
var tot,x0,y0,i,y:longint;
function gcd(x,y:longint):longint;
begin
if y=0 then gcd:=x
else gcd:=gcd(y,x mod y);
end;
begin
tot:=0;
readln(x0,y0);
if y0 mod x0=0
then begin
y:=y0 div x0;
for i:=1 to trunc(sqrt(y)) do
if (y mod i=0) and (gcd(i,y div i)=1) then inc(tot,2);
if y=1 then dec(tot);
end;
writeln(tot);
end.