• 逆元的各种姿势



    %还得写个反斜杠,好烦人

    update 11.1

    get新技能
    求阶乘的逆元 ,注意只是阶乘的逆元
    也是线性的

    inv[n] = f_pow(jc[n],mod - 2); 
    	for(int i = n;i >= 1;-- i) inv[i-1] = inv[i] * i % mod; 
    

    扩展欧几里得求逆元

    (a*a^{-1}≡1(mod p))
    即求 $$aa^{-1}+kp=1(mod p)$$
    因为
    p是质数,(a<p)

    所以 (gcd(a,p)=1)
    进一步转化为(a*a^{-1}+k*p=gcd(a,p))
    恰好的,(exgcd)在求解(gcd)的时候正好可以求出一组解(x,y)解得的(x)即为(4a)(%p)意义下的逆元
    复杂度就当做O(logn)吧

    附带(exgcd)的证明
    求解(a*x+b*y=gcd(a,b))的一组解

    由辗转相除法容易知道
    (gcd(a,b)=gcd(b,a\%b))
    所以
    (b*x+a\%b*y=gcd(b,a\%b))

    (a*x+b*y=gcd(a,b))
    是相等的
    (a*x+b*y=b*x+a\%b*y)
    (a\%b=a-[a/b]*b)
    (a*x+b*y=b*x+(a-a/b*b)*y)
    去括号
    (a*x+b*y=b*x+a*y-[a/b]*b*y)
    结合
    (a*x+b*y=b*x+a*y-[a/b]*b*y)
    (a*x+b*y=a*y+b*(x-[a/b]*y))
    易得
    (x=y)
    (y=x-[a/b]*y)

    void exgcd(int a,int b,int &x,int &y) 
    {
    	if (!b)
    	{
    		x=1;y=0;
    		return;
    	}
    	exgcd(b,a%b,x,y);
    	int tmp=x;
    	x=y;
    	y=tmp-a/b*y;
    }
    int inv_exgcd(int a,int b) 
    {
    	int x,y;
    	exgcd(a,b,x,y);
    	while(x<0) x+=b;
    	return x;
    }
    

    费马小定理求逆元

    前提条件:当p为质数的情况下
    费马小定理
    (a^{p-1}≡1(mod p))
    变形一下
    (a*a^{p-2}≡1(mod p))
    然后我们就很开心的求得了a的逆元啦
    逆元就是(a^{p-2})
    (a)(p-2)次方可以快速幂O(logn)求出

    int f_pow(int a,int b,int p) 
    {
    	int ans=1;
    	while(b) {
    		if(b&1)	ans*=a,ans%=p;
    		a*=a;
    		a%=p;
    		b>>=1;
    	}
    	return ans;
    }
    int inv_feima(int a,int p)
    {
    	return f_pow(a,p-2,p);
    }
    

    线性求逆元

    前提条件:当p为质数的情况下
    线性求逆元,两种方法,这里介绍只一种*
    (那一种求阶乘的在代码量和理解和常数在我感觉下都不如我介绍的优秀,不再介绍)
    (p=k*i+r)
    (k=p/i,r=p\%i)
    (p≡0(mod p))
    (k*i+r≡0(mod p))
    (r≡-k*i(mod p))
    两边同乘(i^{-1},r^{-1}~~是他们两个~~(在mod p意义下))
    得到
    (i^{-1}≡-k*r^{-1}(mod p))
    代入k和r的值
    (i^{-1}≡-p/i*(p\%i)^{-1}(mod p))
    为了求得的逆元是正数,变一下
    (i^{-1}≡(p-p/i)*(p\%i)^{-1}(mod p))
    因为((p\%i)^{-1})在我们之前就求出来了,所以就我们开心的就求出i的逆元啦
    而且代码短

    int inv[1011111];
    void get_inv(int p)
    {
    	inv[0]=inv[1]=1;
    	for(int i=2;i<p;++i)
    		inv[i]=(p-p/i)*inv[p%i]%p;
    }
    

    如果我写错了,欢迎评论提出

  • 相关阅读:
    Leetcode 274.H指数
    Leetcode 273.整数转换英文表示
    Leetcode 264.丑数II
    Leetcode 260.只出现一次的数字III
    Leetcode 242.有效的字母异位词
    Leetcode 241.为运算表达式设计优先级
    Leetcode 240.搜索二维矩阵II
    Leetcode 239.滑动窗口最大值
    Leetcode 237.删除链表中的节点
    Leetcode 236.二叉树的最近公共祖先
  • 原文地址:https://www.cnblogs.com/dsrdsr/p/9503587.html
Copyright © 2020-2023  润新知