菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
468
0

数论学习笔记

原创
05/13 14:22
阅读数 37949

1 整除

  3|6    3整除6    6被3整除

 

2 模运算     

  0<=余数<除数

  (a +-* b) %m=(a%m +-* b%m) %m

  为防止余数为负

  (a - b) %m=(a%m - b%m + m) %m

  常用取模限制结果范围,这时可以在过程中每次取模

 

3 快速幂     

  原理:分治   an=(an/2)2=(an/4)4=...

  不断递归为更小的幂次的平方

  时间复杂度由 O(n) 降为 O(logn)

1 long long fastpow(long long a,int n)
2 {
3     if(n==1)return a;                
4     long long t=fastpow(a,n/2);      
5     if(n%2==1)return t*t*a;          
6     else return t*t;
7 }

   一个更好的非递归版本

 a*a=a2  a2*a2=a4  a4*a4=a8...可以更快得到较高幂次

  借助位运算 a11=a1*2^3 + 0*2^2 + 1*2^1 + 1*2^0

  其实就是查看次数的二进制的每一位是1还是0,是1就乘上对应的数

 1 long long fastpow(long long a,int n)
 2 {
 3     long long ans=1;         
 4     while(n)                
 5     {
 6         if(n&1)ans*=a;
 7         a*=a;
 8         n>>=1;
 9     }
10     return ans;
11 }

 

4  gcd最大公因数 lcm最小公倍数  

  辗转相除法  gcd(a,b)=gcd(b,a%b)   O(logn)  欧几里得算法

  意为如果a为n的几倍,b为n的几倍,a除b剩下的也是n的几倍

  更相减损术  gcd(a,b)=gcd(b,a-b)   O(logn)

  意为如果a为n的几倍,b为n的几倍,a-b一定为n的几倍

  同理 gcd(a,b,c)=gcd(a,b-a,c-a)

  lcm(a,b)gcd(a,b) = ab

  gcd(a,b,c)=gcd(gcd(a,b),c)=gcd(a,gcd(b,c))

  可随意放括号(可重复贡献) lcm也是

  gcd(a,0)=a  gcd(a,b)=gcd(a,-b)

1 int gcd(int a,int b)
2 {
3     return b==0?a:gcd(b,a%b);//辗转相除法
4 }

  思考               

  有理数a b  求最小正整数k  使[ka,kb]内有整数

  我的思路:for(k=1;b*k-floor(a*k)<1;k++);

  (会爆 正解:递归 如果减完b<1求(1/b,1/a)的子问题 没明白为什么 求助)

 

5  裴pei蜀定理(贝组定理)       

  ax+by=gcd(a,b) (a b不全为0的整数) x y必有整数解

  证明:两边除以gcd(a,b)k1x+k2y=1

  a/gcd(a,b) b/gcd(a,b)互质

  gcd(k1,k2)|m (1|1) x y有整数解

  应用:ax+by=m有没有解?如果m是gcd(a,b)的几倍 则有解

  如果ax+by=1有解 则a,b互质    

 

6 扩展欧几里得算法 

  ax+by=c a b c为整数且a b都不为0 设有整数解x=x0 y=y0 

  x=x0-t*b/gcd(a,b) y=y0+t*a/gcd(a,b)为一切整数解 t是整数   

  证明:a*x+b*y=gcd(a,b) -> b*x1+(a%b)*y1=gcd(a,b)

     代入 a%b=a-(a/b)*b  a*y1+b*(x1-a/b*y1)=gcd(a,b)

  x=y1  y=x1-a/b*y1

1 int exgcd(int a,int b,int &x,int &y)
2 {
3     if(b==0){x=1;y=0;return a;}
4     int d=exgcd(b,a%b,x,y);
5     int t=x;x=y;y=t-a/b*y;
6     return d;
7 }

 

7 同余

   ab(mod m) a和b对m同余 = a-b=km

   a-b=km ->ka-kb=k1m

          ->(b+km,m)=(b,m)

          ->a/与m互质的数 b/与m互质的数 对m仍然同余

  一次同余式axb(mod m)(a%m!=0)

  ax-b=ym->ax-my=b

  有解=(系数1,系数2)|右边的常数=(a,m)|b

  ax%m=1(a m互质)x=a'

  (a/b)%m=((a/b)%m * bb'%m)%m=ab'%m

  必有解x=b/a=ba' y=0

 

  逆元的求法 1.扩展欧几里得解方程 2.费马小定理

 

8 费马小定理

  apa对于素数p同余

  证明:{1,2,3,...,p-1}对于p互不同余

  a的因子中没有p {a,2a,3a,...,(p-1)a}对于p互不同余

  它们的余数集合{1,2,3,...,p-1}相同

  它们的元素乘积(p-1)!(p-1)!ap-1(mod p)

  左右除以(p-1)!(p和(p-1)!互质)

  ap-11(mod p) apa(mod p)

  ap-2a'(mod p) a'=ap-2+kp 常用ap-2快速幂求解

 

9 唯一分解定理

  标准分解式a=p1a1p2a2...pkak ai>0 a>1

  (a,b)=p1min(a1,b1)p2min(a2,b2)...pkmin(ak,bk)

  [a,b]=p1max(a1,b1)p2max(a2,b2)...pkmax(ak,bk)

 1 int fac[maxn],power[maxn];
 2 void getprimefactor(int n)
 3 {
 4     for(int i=2;i<=n;i++)
 5     {
 6         while(n%i==0)
 7         {
 8             n/=i;           //除去找到的因子 保证找到的总是质数
 9             fac[++cnt]=i;   //记录
10             power[cnt]++;
11         } 
12     }
13 }
 1 void getprimefactor(int n)
 2 {
 3     for(int i=1;i<=N&&pri[i]*pri[i]<=n;i++)
 4     {
 5         while(n%pri[i]==0)              //只在素数中找
 6         {
 7             n/=pri[i];
 8             fac[++cnt]=i;
 9             power[cnt]++;
10         }
11     }
12     if(n>1)fac[++cnt]=n,power[cnt]=1;//n是个素数
13 }

 

10 素数筛

  埃式筛法 仍然有重复 2和3都筛24 O(nloglogn)

  从素数*素数开始标记素数*(素数+1)、素数*(素数+2)...为合数

 1 int getprime(int n)
 2 {
 3     for(int i=2;i<=n;i++)isprime[i]=1;//默认是素数
 4     isprime[0]=isprime[1]=0;        //0、1不是素数
 5     for(int i=2;i<=n;i++)   
 6     {
 7         if(isprime[i]) 
 8         {
 9             prime[++cnt]=i;               //记录
10             for(int j=i*i;j<=n;j+=i)isprime[j]=0;//尚未遍历的素数倍数
11         }
12     }
13 }

  欧拉筛 无重复 O(n) 2->4  3->6-9  4->8  5->10-15-25  6->12

  每一个合数被其最小质因子筛掉

 1 int getprime(int n)
 2 {
 3     for(int i=2;i<=n;i++)
 4     {
 5         if(!isprime[i])pri[++cnt]=i;
 6         for(int j=1;j<=cnt;j++)
 7         {
 8             if(i*pri[j]>n)break;
 9             isprime[i*pri[j]]=1;
10             if(i%pri[j]==0)break;
11         }
12     }
13 }

 

 

11 欧拉函数

  φ(n) 和n互质<=n数的个数

  φ(1)=1 质数pφ(p)=p-1

  积性函数 如果(a,b)=1 φ(a*b)=φ(a)*φ(b)

  φ(n)=nΠi=1s (1-1/pi)

  n前和n互质的数的个数=n*(1-1/质因数1)(1-1/质因数2)...

  φ(n)=Πi=1sφ(piki)(唯一分解定理)

       =Πi=1s(pi-1)piki-1

       =Πi=1spik

发表评论

0/200
468 点赞
0 评论
收藏