zoukankan      html  css  js  c++  java
  • 逆元学习笔记

    明天就要出去听课,第一天就讲数论搞得我很方,于是趁现在赶紧把我的数论坑补补

    逆元

    逆元定义

    (a imes xequiv 1 pmod b)(a)(b)互质,则称(x)(a)的逆元,记为(a^{-1})

    逆元求法

    扩展欧几里得

    利用扩展欧几里得求线性同余方程(a imes xequiv cpmod b)

    我们知道扩展欧几里得可以求出线性方程组的系数,所以我们就可以求出当(c=1)的情况的线性方程组,则可以转换为

    [a imes x+b imes y=1 ]

    此时(x)就是我们要求的逆元

    LL exgcd(LL a,LL b,LL &x,LL &y) {
    	LL d=0;
    	if(!b)x=1,y=0,d=a;
    	else {
    		d=exgcd(b,a%b,y,x);
    		y -= (a/b)*x;
    	}
    	return d;
    }
    main(){
    	exgcd(a,b,x,y);
    	x=(x%b+b)%b;
    	printf("%lld
    ",x);
    }
    

    费马小定理

    下面是费马小定理的定义

    (p)为素数,(a)为正整数,且(a、p)互质,则就有下列通项公式

    [a^{p-1}equiv 1 pmod p ]

    所以根据逆元的定义与费马小定理的定义

    [egin{aligned} a imes x&equiv 1 & pmod b \ a imes x&equiv a^{p-1} & pmod b \ x&equiv a^{p-2} &pmod b end{aligned} ]

    所以我们就可以用快速幂快速求出(a^{p-2}pmod b)的值了,这个就是他的逆元

    LL ksm(LL x,LL y) {
        LL z=1;
        while(y) {
            if(y&1) z=(z*x)%p;
            x=(x*x)%p;
            y>>=1;
        }
        return z;
    }
    main(){
        printf("lld
    ",ksm(i,p-2));
    }
    

    线性求逆元

    这个其实理解起来也比较简单。
    线性求逆元,我们就要用递推的形式,设(A[i])为第(i)个数的逆元。
    首先我们知道(1)的逆元是(1)
    然后我们设(p=k imes i+r),然后将此式子放到(mod p)意义下:
    (k imes i+requiv 0pmod p)
    然后两边同时乘上(i^{-1},r^{-1})就会得到

    [egin{aligned} k imes r^{-1}+i^{-1}&equiv0 & pmod p\ i^{-1}&equiv -k imes r^{-1} & pmod p\ i^{-1}&equiv -left[frac{p}{i} ight] imes p mod i^{-1} & pmod p end{aligned} ]

    于是递推式就是下方

    A[i] = -(p/i)*A[p % i];
    

    更博更博

    逆元的应用

    求组合数

    我们可以预处理出阶乘,然后如果有模数的话就可以求

    for(int i=1;i<=n;i++) fac[i]=fac[i-1]*i,inv[i]=ksm(fac[i],mod-2);
    LL c(int n,int m){
        return fac[n] * inv[m]%mod * inv[n-m]%mod;
    }
    
  • 相关阅读:
    一段关于生成器代码的解读
    (十三)内置函数
    (十二)生成器和生成器函数,推导式和表达式
    (十一)函数名的使用,闭包,迭代器
    (十)函数的动态传参,作用域
    (九)函数
    (八)文件操作
    (七)深浅拷贝
    (六)id(),is和==,内存常量
    (五)字典,集合
  • 原文地址:https://www.cnblogs.com/ifmyt/p/9722242.html
Copyright © 2011-2022 走看看