zoukankan      html  css  js  c++  java
  • 数♀论总♂结

    太容易忘记数论的定理了,(也许是比较),所以开了个坑来记一下定理.

    1.最大公因数,最小公倍数

    gcd(a,b)=gcd(b,a%b) (最大公因数)

    lcm(a,b)=a*b/gcd(a,b) (最小公倍数)

    2.莫比乌斯反演

       μ(x)={   1              (x==1)

                    (-1)^k       (x是由k个互不相同的质数相乘)

                    0               (其他情况)}

     (莫比乌斯太难了,以后懂了记得填坑)

     筛法求莫比乌斯函数

     1 #include <cstdio>  
     2 #include <cstring>  
     3 using namespace std;  
     4 const int maxn = 60000+5;  
     5 bool vis[maxn];  
     6 int prime[maxn],primes,mu[maxn];  
     7 void init_mu()  
     8 {  
     9     memset(vis,0,sizeof(vis));  
    10     mu[1]=1;  
    11     primes=0;  
    12     for(int i=2; i<maxn; i++)  
    13     {  
    14         if(!vis[i]){  
    15             prime[primes++]=i;  
    16             mu[i]=-1;  
    17         }  
    18         for(int j=0; j<primes&&i*prime[j]<maxn; j++)  
    19         {  
    20             vis[i*prime[j]]=1;  
    21             if(i%prime[j]) mu[i*prime[j]]=-mu[i];  
    22             else { mu[i*prime[j]]=0;break;}  
    23         }  
    24     }  
    25 }  

    -2016-06-20 终于看懂一点点。。。,

        这玩意常常用来求gcd的关系。

        f(i)是i=gcd(x,y),g(i)是i|gcd(x,y)

        那么f(n)=d|n  u(n/d)*g(d)

    如果有式子满足f(n)=Σ d|n a(d)*b(n/d)

    我们通常表示为f=a*b,这是卷积的表示,其中,如果f(n)=Σ d|n a(d),那么我们表示为f=a*1,

    1实际上代表单位卷积。1*1代表的是除数函数中x等于0的情况:

    卷积满足交换律和结合律。。

    -2016-06-20

    3.欧拉函数

      欧拉函数属于积性函数(gcd(a,b)==1,f(a*b)=f(a)*f(b)),不是完全积性函数(任何情况 f(a*b)=f(a)*f(b))

      若x为质数 phi(x)=x-1;

      若x为奇数 phi(2*x)=phi(x)*2

      若x为p^k,p为质数 phi(x)=x-x/p=p^k-p^(k-1)=(p-1)*p^(k-1) (因为除了p的倍数以外,都和x互质)

      若a,b互质,b为质数,phi(a*b)=phi(a)*(b-1)      

      欧拉定理:若a,n互质 则有 a^(phi(n))= 1 (mod n)

      O(n)筛法:

      

     1 void getphi()
     2 {
     3     phi[1]=1;
     4     for(int i=2;i<=n;i++)
     5     {
     6         if(!mark[i]){phi[i]=i-1;pri[++tot]=i;}
     7         for(int j=1;j<=tot;j++)
     8         {
     9             int x=pri[j];
    10             if(i*x>n)break;
    11             mark[i*x]=1;
    12             if(i%x==0){phi[i*x]=phi[i]*x;break;}
    13             else phi[i*x]=phi[i]*phi[x];
    14         }
    15     }
    16 }
     1 //直接求解欧拉函数  
     2 int euler(int n){ //返回euler(n)   
     3       int res=n,a=n;  
     4       for(int i=2;i*i<=a;i++){  
     5           if(a%i==0){  
     6               res=res/i*(i-1);//先进行除法是为了防止中间数据的溢出   
     7               while(a%i==0) a/=i;  
     8           }  
     9       }  
    10       if(a>1) res=res/a*(a-1);  
    11       return res;  
    12  }  

    4.exgcd

    已知a,b求解x,y满足a*x+b*y=gcd(a,b)

    若a==1,b==0 则x=1,y=0;

    若已知下一层x,y

    则当前t=x  x=y  y=t-a/b*y;

    由于gcd(a,b)=gcd(b,a%b)

    则有ax+by=bx+(a%b)y

          ax+by=bx+(a-a/b*b)y

          ax+by=ay+b*(x-a/b*y)

    注意:如求某数N的逆元,则令a=N,b=p(假如是在模p下),如果令b=0会错误.

    EXGCD求线性方程组:

     

    5.原根

      如果模p有原根,那么它一定有 phi(phi(p))个原根。

      若有(g^i )%p(0<i<=p-1) 两两不同,则称g为p原根。

      若p为素数,p一定有原根。g^(P-1) = 1 (mod P)(p为素数)

      m有原根的充要条件:m=2,4,2*p^a,p^a                 其中p为奇素数          

      原根通常很小,往往暴力求

      求模素数p的原根:

         对p-1质因数分解,分解成 p1^k1*p2^k2*p3^k3...pn^kn=p-1

         对于一个数g若恒有 g^((p-1)/pi)!=1 (mod p)则g就是p的原根。

      对合数p的原根:

        讲上述p-1换成phi(p)即可。

    6.逆♂元

      若有a*x==1 (mod p),则称x是a在模p下的逆元

      逆元运用广泛,可以进行转换等

      6.1    

             (若a,p互质)a^phi(p)==1 (mod p) (费马小定理)

             即有 a^(phi(p)-1)== a^(-1) (mod p)

             即若p为质数,a在p下的逆元即是 (a^(p-2))%p;

      6.2  

            若a/b中有b|a,现求a/b (mod p)

            a/b=k*p+x (x即为a/b (mod p))

            a=k*p*b+b*x

            a%pb=b*x

            x=(a%pb)/b

     6.3

           有些题目需要用到1->M 模M的所有逆元,我们有一个非常好♂用的顺推公式

           inv[i]=(M-M/i)*inv[M%i]%M

           证明如下:

                设t=M/i,k=M%i

                i*t+k=0 (mod M)

                -i*t==k(mod M) 两边同时除以i*k得到

                -t*inv[k]==inv[i](mod M)

                inv[i]=-t*inv[k]将t=M/i,k=M%i带入可得上式

    6.4

            ax==b(mod p)

            求最小解x

            首先若gcd(a,p)不是b的因数则无解,否则将a,b带入exgcd(a,b,x,y)算出其中x即是满足上式的x

    6.5

           求阶乘的逆元?若p为素数

           可以先让f[n]=((!n)%p)^(p-2)%p

           然后从n-1往1:f[i]=f[i+1]*i%p就行辣!

           简单来说就是先求 总阶乘的逆元,然后倒着乘回去

    7.二次剩余

           二次剩♂余:x^2== a(mod p)

           有解则a为p的二次剩余,否则a是p的二次非剩余

           若 a^((p-1)/2)==1(mod p)a是p的二次剩余

    8.指标

           指标:定义指标为I(A),那么I(A)就是最小令g^I(A)==A (mod p) 其中g是p的原根,若有x^a==b(mod c)则有 a*I(x)==I(b)(Mod(c-1))   PS:通常我们计算出原根基本都会用再预处理出指标

    9.裴蜀定理

            ax+by=gcd(a,b)一定有解

    10.求幂大法和降幂大法

            a^b Mod B=A^(b Mod phi(B)+phi(B)) %Mod B (其中b>=phi(B)) 求幂大法

            p为素数 X^a%p=X^(a%(p-1))%p 降幂大法

    11.组合数

           运用广泛

    11.1

           杨辉三角:C[i][j]=C[i-1][j-1]+C[i-1][j] 计算时间O(N^2)

    11.2

           lucas定理 用于求C(n,m)%p, p为素数

           Lucas(n,m)=C(n%p,m%p)*Lucas(n/p,m/p) 

     1 typedef long long LL;
     2 using namespace std;
     3 
     4 LL exp_mod(LL a, LL b, LL p) {
     5     LL res = 1;
     6     while(b != 0) {
     7         if(b&1) res = (res * a) % p;
     8         a = (a*a) % p;
     9         b >>= 1;
    10     }
    11     return res;
    12 }
    13 
    14 LL Comb(LL a, LL b, LL p) {
    15     if(a < b)   return 0;
    16     if(a == b)  return 1;
    17     if(b > a - b)   b = a - b;
    18 
    19     LL ans = 1, ca = 1, cb = 1;
    20     for(LL i = 0; i < b; ++i) {
    21         ca = (ca * (a - i))%p;
    22         cb = (cb * (b - i))%p;
    23     }
    24     ans = (ca*exp_mod(cb, p - 2, p)) % p;
    25     return ans;
    26 }
    27 
    28 LL Lucas(int n, int m, int p) {
    29      LL ans = 1;
    30 
    31      while(n&&m&&ans) {
    32         ans = (ans*Comb(n%p, m%p, p)) % p;
    33         n /= p;
    34         m /= p;
    35      }
    36      return ans;
    37 }
    38 
    39 int main() {
    40     Read();
    41     int n, m, p;
    42     while(~scanf("%d%d%d", &n, &m, &p)) {
    43         printf("%lld
    ", Lucas(n, m, p));
    44     }
    45     return 0;
    46 }

    11.3

           组合数取模?

           C(n,m)=!n/(!(n-m)*!(m))

           因此我们可以使用6.5中求阶乘逆元的方式,求出!(n-m)和!(m)在模下的逆元,然后相乘再乘上!n模模数就是答案!

    12.BSGS (拔山盖世(雾))

          a^x==b(mod p)

          令x=i*m+j,其中m=ceil(sqrt(p) 

          a^(i*m+j)==b(mod p)

         那么有

         a^(j)==a^(-i*m)*b(mod p)其中a^(-i*m)就是a^(i*m)在模P下的逆元

        那么我们只要枚举j,用哈希表存下 a^j %p,然后再枚举a^(-i*m)*b (mod p),在哈希表下查找就可以了

        至于为什么要这样找和为什么m=ceil(sqrt(p)),我是不懂的。

    13.质数

    13.1     大于等于sqrt(n)的n的质因子不会超过一个

    13.2    在!n内质因子p的出现个数为 n/p+n/(p^2)+n/(p^3)...+n/(p^k) (p^(k+1)刚好大于n)

    13.3    筛法求质数

     1 typedef long long LL;  
     2 #define mn 100000+5  
     3 LL ph[mn];  
     4 bool vis[mn];  
     5 int primes, prime[mn];  
     6 void Init()  
     7 {  
     8     ph[1] = 1;  
     9     primes=0;  
    10     for (LL i = 2; i < mn; ++i)  
    11     {  
    12         if (!vis[i])  
    13         {  
    14             prime[primes++] = i;  
    15             ph[i] = i-1;  
    16         }  
    17         for (LL j = 0; j < primes && i*prime[j] < mn; ++j)  
    18         {  
    19             vis[i*prime[j]] = true;  
    20             if (i % prime[j])  
    21                 ph[i*prime[j]] = ph[i]*(prime[j]-1);  
    22             else  
    23             {  
    24                 ph[i*prime[j]] = ph[i]*prime[j];  
    25                 break;  
    26             }  
    27         }  
    28     }  
    29 }  

        这个算法的关键在于 if(i%pr[j] == 0) break;。它使得任何一个合数,只被它最小的质因数标记过一次

          

           

  • 相关阅读:
    pdf在线转换器
    抖音修复老照片动起来笑起来的程序app的下载地址
    FFmpeg.AutoGen Unable to load DLL 'avutil.56' 解决方法
    Array.prototype.fill 填充值被复用的问题
    Recoil Input 光标位置被重置到末尾的问题
    TypeScript 扩展全局 Window 时报错的解决
    Recoil 中默认值的正确处理
    Recoil 中多级数据联动及数据重置的合理做法
    Recoil 默认值及数据级联的使用
    Recoil 的使用
  • 原文地址:https://www.cnblogs.com/qzqzgfy/p/5326949.html
Copyright © 2011-2022 走看看