数论总结

来源:互联网 发布:风靡网络的恐怖推理图 编辑:程序博客网 时间:2024/06/06 05:24

前言:走进区域赛,切实的发现数论和思维的重要性,于是弱鸡努力总结一波!
(STL中可以用nth_element求得类似的第n大的数)

一:约数个数定理

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

二:整除的基本性质

a|b b|c => a|c
a|b a|c => a|bc
a|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的公因数

三:互素性质

a与b,c同时互素=>a与b∗c互素p为素数且p|a∗b=>p|a  or  p|ba∗b|c  and  gcd(a,c)=1=>b|cgcd(ak,b)=1  {k>=1}=>gcd(a,b)=1a≡1(modb)=>gcd(a,b)=1

四:算术基本定理

任何一个大于1的自然数n,都可以唯一分解成有限个质数的乘积n=pr11∗pr22∗...∗prkkp1<p2<...<pk均为质数,r1,r2,...rk均为正整数

五:扩展欧几里得算法(exgcd)

求不定方程 a∗x+b∗y=1 的一组解的方法由 a∗x1+b∗y1=gcd(a,b)=gcd(b,amod b)=b∗x2+[a−⌊a/b⌋∗b]∗y2=a∗y2+b∗(x2−y2∗⌊a/b⌋)=>x1=y2=>y1=x2−y2∗(a / b)

用途:
1)求解不定方程;
2)求解模线性方程(线性同余方程);
3)求解模的逆元;

1)求解不定方程

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

(1)先计算Gcd(a,b),若n不能被Gcd(a,b)整除,则方程无整数解;否则,在方程两边同时除以Gcd(a,b),得到新的不定方程a2∗x+b2∗y=n2此时Gcd(a2,b2)=1;(2)利用扩展欧几里德算法求出方程a2∗x+b2∗y=1的一组整数解x0,y0,则n2∗x0,n2∗y0是方程a2∗x+b2∗y=n2的一组整数解;(3)根据数论中的相关定理,可得方程a2∗x+b2∗y=n2的所有整数解为:x=n2∗x0+b2∗ty=n2∗y0−a2∗t (t=0,1,2,……)调整得到正整数解
LL exgcd(LL a, LL b, LL &x, LL &y) {      if(!b) {          x = 1;          y = 0;          return a;      }      LL ans = exgcd(b, a%b, x, y);      LL temp = x;      x = y;      y = temp - a / b * y;      return ans;  }  LL cal(LL a, LL b, LL c) {      LL x, y;      LL gcd = exgcd(a, b, x, y);      if(c % gcd != 0) return -1;      x *= c / gcd;      b /= gcd;      if(b < 0) b =- b;      LL ans = x % b;      if(ans <= 0) ans += b;      return ans;  } 

六:欧拉函数
性质

φ(n)表示n以内与n互素(包括1)的数的个数欧拉定理:若a与n互质,那么有aφ(n)≡1(mod  n)用于求乘法逆元若p是一个质数,那么φ(p)=p−1,注意φ(1)=1。积性函数    若m与n互质,那么φ(n∗m)=φ(n)∗φ(m)    n=pk且p为质数,那么φ(n)=pk−p(k−1)=p(k−1)∗(p−1)   当n为奇数时有φ(2∗n)=φ(n)∑d|n φ(d)=n欧拉函数公式:(我们假设n的质因子有x,y) euler[n] = n * (1-1/x) * (1-1/y)。若有多个继续添上即可。

欧拉函数拓展:小于或等于n的数中(n > 1),与n互质的数的总和为:euler[n] * n / 2。

O(N)求解1∼n的φ(i)表:

void euler() {      int i, j;      eu[1] = 1;//1的欧拉函数为1 看题目而定       for(i = 2; i < MAX; i++) {          if(!eu[i]) {              for(j = i; j < MAX; j += i) {                  if(!eu[j]) eu[j] = j;                  eu[j] = eu[j] * (i-1) / i;              }         }      }  } 

O(n√)求解φ(n):

int euler(int n) {//求n的欧拉函数          int eu = n;//欧拉函数       for(int i = 2; i*i <= n; i++) {          if(n % i == 0) {//质因子               eu = eu * (i-1) / i;              while(n % i == 0)              n /= i;//避免再次累加           }       }      if(n > 1) eu = eu * (n-1) / n;//本身就是 质数       return eu;  }  

七:逆元(费马+快速幂 || exgcd)
费马小定理:a,p互质,则 a^(p - 1) % p = 1;
等比数列的前n项和逆元:[ (q^n - 1) / (q - 1) ] * [ (q - 1)^(mod - 1) % mod] % mod = s = (q^n - 1) * (q - 1)^(mod - 2) % mod;

八:唯一分解定理

1.有多少个约数:
先分解质因数
因数的次数分别是4,2,1
所以约数的个数为(4+1)(2+1)(1+1)=5*3*2=30个
例:
先分解质因数
720=24*32*51
因数的次数分别是4,2,1
所以约数的个数为(4+1)(2+1)(1+1)=5*3*2=30个

2.所有约数之和:
如何求一个数所有约数之和呢?
首先,应用算术基本定理,化简为素数方幂的乘积。
X = a1^k1 * a2^k2……..an^kn
X的所有素数之和可用公式(1+a1 + a1^2…a1^k1) * (1+a2 + a2^2…a2^k2) * …..(1+an + an^2…an^kn);
如:
2004 = 2^2 * 3 *167
2004所有因子之和为(1 + 2 + 2^2) * (1 + 3) * ( 1 + 167) = 4704;
程序实现的时候,可利用等比数列快速求1 + a1 + a1^2 + …..a1^n;

void init() { //素筛    memset(p,0,sizeof(p));      memset(a,0,sizeof(a));      a[0]=a[1]=1;      for(int i=2;i*i<=max_n-5;i++) {          if(!a[i]) {              for(int j=i+i;j<=max_n-5;j+=i)                  a[j]=1;          }      }      for(int i=1;i<=max_n-5;i++) {          if(!a[i])              p[k++]=i;      }  }  LL nop(LL n) {      LL ans=1;      for(int i=0;i<k;i++) {          if(p[i]>n) break;          LL res=0;          while(n%p[i]==0) {              res++;              n/=p[i];          }          ans=ans*(res+1);      }      if(n>1) ans*=2;//注意这一步      return ans;  }  

后续补充~~~

原创粉丝点击