数论总结

来源:互联网 发布:请问在淘宝怎么开店 编辑:程序博客网 时间:2024/06/05 19:50

定理/性质

1~n:nln(n)(实际偏小,越趋近于+越准确,估计复杂度是够的)

约数个数定理

定义g(x),为x的约数个数
对于一个数i,可分解成若干质数幂次的乘积,即
i=prime[1]aprime[2]b.....
g(i)=(a+1)(b+1)......

整除的基本性质

a|b b|c   =>   a|ca|b a|c   =>   a|bca|b a|c   =>   a|ib±jc   (a|b,c的线性组合)a|b b|a   =>   a=±b

a=ib±c => 公因子(a,b)=公因子(b,c)

  • 证明
    • 假设d为b,c的公因子,即d|b,d|c
    • 则 d|ib±c=a,即d|a
    • 由d|b得 d=公因子(a,b)=公因子(b,c)
    • 反之,如果d是a,b的公因数,也能证出d是b,c的公因数

互素性质

  • ab,c=>abc
  • pp|ab=>p|a  or  p|b
  • ab|c  and  gcd(a,c)=1=>b|c
  • gcd(ak,b)=1  {k>=1}=>gcd(a,b)=1
  • a1(modb)=>gcd(a,b)=1

算术基本定理

  • 任何一个大于1的自然数n,都可以唯一分解成有限个质数的乘积
  • n=pr11pr22...prkk
  • p1<p2<...<pk,r1,r2,...rk

模运算

  • (a+b)  mod  n=(a  mod  n+b  mod  n)  mod  n
  • (ab)  mod  n=(a  mod  nb  mod  n)  mod  n
  • ab  mod  n=(a  mod  n)b  mod  n
  • 切记 除法运算 不能模运算!!!

算法

欧几里得算法(gcd)

辗转相除

function gcd(a,b:longint):longint;begin if b=0 then gcd:=a else gcd:=gcd(b,a mod b);end;

辗转相减(更相减损术/Stein算法)

  • a为偶数,b为奇数 gcd(a,b)=gcd(a/2,b)
    a为奇数,b为偶数 gcd(a,b)=gcd(a,b/2)
    a为偶数,b为偶数 gcd(a,b)=2*gcd(a/2,b/2)
    a为奇数,b为奇数 gcd(a,b)=gcd(b,a-b) {a>b}
    (a或b=0 返回另一个值)或(a=b返回a或b)
  • 证明gcd(a,b)=gcd(b,a-b)
    • a=b+(a-b)=>(a,b)=(b,a-b) {整除性质}
function gcd(a,b:longint):longint;begin if a=0 then exit(b) else  if b=0 then exit(a)  else   if a=b then exit(a); if a mod 2=0 then  if b mod 2=0  then gcd:=2*gcd(a div 2,b div 2)  else gcd:=gcd(a div 2,b) else  if b mod 2=0  then gcd:=gcd(a,b div 2)  else   if a>b   then gcd:=gcd(b,a-b)   else gcd:=gcd(b,b-a);end;
  • 优点:
    • 加法,减法和移位运算,是最基本的运算,时间消耗最小
    • 乘法,除法,取余运算较慢

扩展欧几里得算法(exgcd)

  • 求不定方程 ax+by=1 的一组解的方法

  • ax1+by1=gcd(a,b)=gcd(b,amod b)=bx2+[aa/bb]y2=ay2+b(x2y2a/b)

  • =>x1=y2

  • =>y1=x2y2(a / b)
procedure exgcd(a,b:int64;var d,x,y:int64);var t:int64;begin  if b=0  then   begin d:=a; x:=1; y:=0; end  else   begin exgcd(b,a mod b,d,x,y); t:=x; x:=y; y:=t-y*(a div b); end;end;
  • 用途:
    • 1)求解不定方程;
    • 2)求解模线性方程(线性同余方程);
    • 3)求解模的逆元;

1)求解不定方程

利用扩展欧几里得算法求解不定方程ax+by=n的整数解的求解全过程,步骤如下:

  • (1)先计算Gcd(a,b),若n不能被Gcd(a,b)整除,则方程无整数解;否则,在方程两边同时除以Gcd(a,b),得到新的不定方程a2x+b2y=n2此时Gcd(a2,b2)=1;

  • (2)利用扩展欧几里德算法求出方程a2x+b2y=1的一组整数解x0,y0,则n2x0,n2y0a2x+b2y=n2

  • (3)根据数论中的相关定理,可得方程a2x+b2y=n2的所有整数解为:
    x=n2x0+b2t
    y=n2y0a2t (t=0,1,2)
    调整得到正整数解

最小公倍数(lcm)

  • lcma,b=ab/gcd(a,b)

快速幂

  • 其实就是倍增的思想
  • a1,a2,a4...a2n
  • 所以快速+幂/乘/加 都可以

ab mod n

  • b and 1 取出二进制下最后一位
  • b shr  1 去掉二进制下最后一位
  • ab=a2n......a16a8a4a2
  • 每次求出a2i,1a2i
function f(a,b,n:int64):int64;  //(a^b) mod nvar t,y:int64;begin t:=1; y:=a; while b<>0do  begin  if(b and 1)=1  then t:=t*y mod n;   y:=y*y mod n;   b:=b shr 1;  end; exit(t);end;

[acbd]n

矩阵乘法求斐波那契数列
[F[N1]F[N]]=[acbd][F[N2]F[N1]]

{F[N1]=aF[N2]+bF[N1] F[N]=cF[N2]+dF[N1]
a=0b=1c=1d=1
[F[N1]F[N]]=[0111][F[N2]F[N1]]
[F[N1]F[N]]=[0111]N1[F[0]F[1]]

var x:array[0..100000000]of longint; i,j,k,n:longint; t,y:array[1..2,1..2]of int64;function g(f:longint):longint;var a,b,c,d:longint;begin t[1,1]:=1; t[1,2]:=0; t[2,1]:=0; t[2,2]:=1; y[1,1]:=0; y[1,2]:=1; y[2,1]:=1; y[2,2]:=1; k:=1000000007; while f<>0 do  begin   if (f and 1)=1   then begin    a:=(t[1,1]*y[1,1]+t[1,2]*y[2,1])mod k;    b:=(t[1,1]*y[1,2]+t[1,2]*y[2,2])mod k;    c:=(t[2,1]*y[1,1]+t[2,2]*y[2,1])mod k;    d:=(t[2,1]*y[1,2]+t[2,2]*y[2,2])mod k;    t[1,1]:=a mod k; t[1,2]:=b mod k; t[2,1]:=c mod k; t[2,2]:=d mod k;   end;   a:=(y[1,1]*y[1,1]+y[1,2]*y[2,1])mod k;   b:=(y[1,1]*y[1,2]+y[1,2]*y[2,2])mod k;   c:=(y[2,1]*y[1,1]+y[2,2]*y[2,1])mod k;   d:=(y[2,1]*y[1,2]+y[2,2]*y[2,2])mod k;   y[1,1]:=a mod k; y[1,2]:=b mod k; y[2,1]:=c mod k; y[2,2]:=d mod k;   f:=f shr 1;  end; exit((x[1]*t[2,1]+x[0]*t[2,2])mod k);end;begin readln(n); k:=1000000007; x[0]:=1; x[1]:=1; writeln(g(n-1)); for i:=2 to n do  x[i]:=(x[i-1]+x[i-2])mod k; writeln(x[n]);end.

矩阵乘法优化递推式

例如a[n]=a[n1]+a[n2]+5
a[N1]a[N]1=110100501a[N2]a[N1]1

线性筛

var prime:array[0..3562115]of longint; check:array[0..60000000]of boolean; i,j:longint; n,len:longint;begin readln(n); for i:=2 to n do  begin   if check[i]=false   then begin inc(len); prime[len]:=i; end;   for j:=1 to len do    begin     if i*prime[j]>n then break;     check[i*prime[j]]:=true;     if i mod prime[j]=0 then break;    end;  end; writeln(len); for i:=1 to len do  write(prime[i]);end.

判断素数

O(N)

我们知道对于一个的他的因子的大小不超过N,所以线性筛预处理,再取模判断即可

O(log2n)

  • :p  apa(modp)ap11(modp)
  • a,2<a<p,ap(modp)
  • anaφ(n)1(mod  n)
  • pφ(p)=p1φ(1)=1
  • 积性函数
    • mnφ(nm)=φ(n)φ(m)
    • n=pkpφ(n)=pkp(k1)=p(k1)(p1)
  • nφ(2n)=φ(n)
  • d|n φ(d)=n
  • φ(n)=npp|np1p

O(N)1nφ(i)

const maxn=1000000;var check:array[0..maxn]of boolean; phi,prime:array[0..maxn]of longint; n,i,j,ans,len:longint;begin readln(n); len:=0; for i:=2 to n do  begin   if check[i]=false   then begin inc(len); phi[i]:=i-1; prime[len]:=i; end;   for j:=1 to len do    begin     if prime[j]*i>n     then break;     check[i*prime[j]]:=true;     if i mod prime[j]=0     then begin phi[i*prime[j]]:=phi[i]*prime[j]; break; end     else phi[i*prime[j]]:=phi[i]*(prime[j]-1);    end;  end; for i:=1 to n do  writeln(phi[i]);end.

O(n)φ(n)

const maxn=1006350;var check:array[0..maxn]of boolean; prime:array[0..maxn]of longint; i,j:longint; n,s,ans,len,t:longint;begin readln(n); s:=n; ans:=n; n:=trunc(sqrt(n)); len:=0; for i:=2 to n do  begin   if check[i]=false   then begin inc(len); prime[len]:=i; end;   for j:=1 to len do    begin     if prime[j]*i>n     then break;     check[prime[j]*i]:=true;     if i mod prime[j]=0     then break;    end;  end; for i:=1 to len do  begin   if s mod prime[i]=0   then    begin     ans:=(ans div prime[i])*(prime[i]-1);     while s mod prime[i]=0 do      s:=s div prime[i];    end;  end; if s<>1 then ans:=(ans div s)*(s-1); //1700016764 writeln(ans);end.

莫比乌斯函数

性质

  • n
    d|nμ(d)={10d=1d>1
  • n:
    d|nμ(d)d=φ(n)n

O(N)1nμ(i)

const maxn=100000;var check:array[0..maxn]of boolean; mu,prime:array[0..maxn]of longint; i,j,len,n:longint;begin readln(n); mu[1]:=1; len:=0; for i:=2 to n do  begin   if check[i]=false   then begin mu[i]:=-1; inc(len); prime[len]:=i; end;   for j:=1 to len do    begin     if i*prime[j]>n     then break;     check[i*prime[j]]:=true;     if i mod prime[j]=0     then begin mu[i*prime[j]]:=0; break; end     else mu[i*prime[j]]:=-mu[i];    end;  end; for i:=1 to n do  writeln(i,' ',mu[i]);end.

求解模方程组

中国剩余定理可以求解模数互质的情况,但根据ydc的课件,我们用其他方式合并

{x  mod  a1=b1x  mod  a2=b2

{x=a1x1+b1x=a2y1+b2

a1x1+b1=a2y1+b2

扩展欧几里得求出x1
b=a1x1+b1  a=lcm(a1,a2)
然后我们合并为x  mod  a=b

求逆元

求逆元的方法汇总

0 0
原创粉丝点击