• 乘法逆元


    乘法逆元

    若整数(b,p)互质,并且(b|a),则存在一个整数(x)使得(a/b≡a*x(mod p)) ,则称(x)(b) mod (p)的乘法逆元

    记为(b-1)(mod (p)

    我们先来看看有什么用

    当输出结果很大时,要模一个mod再输出

    ((a+b)\%mod=a\%mod+b\%mod)

    ((a-b)\%mod=a\%mod-b\%mod)

    ((a*b)\%mod=a\%mod*b\%mod)

    ((a/b)\%mod)

    乘法逆元派上用场了,设(b)(p)的乘法逆元为(inv)

    ((a/b)\%p=(a*inv)\%p=a\%p*inv\%p)

    为什么呢? 因为(b*inv≡1(mod p))

    (a/b*b*inv=a*inv≡ a/b(mod p))
    举个例子 要求(110/10)%7

    (11x≡1 (mod 7) x=9)

    ((110/10)\%7=(110\%7)*(9\%7)=5*2\%7=3)

    接下来是三种代码实现

    1扩展欧几里得(exgcd) O(nlogn)

    (ax!≡1)(mod (p)) 设(ax=yp+1,b=-p)(ax+by=1)

    void exgcd(int a,int b)
    {
        if(b==0) g=a,x=1,y=0;
        else{
            exgcd(b,a%b);
            int x1=y,y1=x-a/b*y;
            x=x1,y=y1;
            printf("%d*(%d)+%d*(%d)=%d
    ",a,x,b,y,g);
        }
    }
    inv[a]=(x+p)%p;
    

    2费马小定理O(nlogn)

    复杂度 欧拉函数(O(n)),快速幂(O(logn))

    假如(p)是质数,且(gcd(a,p)=1),那么 (a^{p-1}≡1)(mod (p))

    由费马小定理 (a^{p-1} ≡1)$ , 变形得$$aa^{p-2}≡1((mod p),答案已经很明显了:若)a,p(互质,因为且)aa^{p-2}≡1$$(mod p)且a*x≡1(mod p)(,则)x=a^{p-2}$,用快速幂可快速求之.

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    const int N=3e6+5;
    inline int read() {
    	int x=0;char ch=getchar();
    	while(!isdigit(ch)) ch=getchar();
    	while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
    	return x;
    }
    typedef long long LL;
    int n,p;
    inline LL qpow(LL a,LL b) {
    	LL ans=1;
    	while(b) {
    		if(b&1) ans=ans*a%p;
    		a=a*a%p;
    		b>>=1;
    	}
    	return ans;
    }
    int main() {
    	n=read();p=read();
    	for(int i=1;i<=n;+i++)
    		printf("%d
    ",qpow(i,p-2));
    	return 0;
    }
    
    

    3欧拉定理O(nlogn)

    定理内容:如果(a,p)互质,那么(a^φ(p) ≡ 1),当 p 为质数时,(φ(p)=p-1)

      同理,结合同余方程,得 (x=a^{p-2})(mod p),用快速幂可快速求之即可

    代码同上

    4线性递推 O(n)

    #include<bits/stdc++.h>
    using namespace std;
    #define N 3000010
    typedef long long ll;
    int n,p;
    ll inv[N];
    int main(){
        scanf("%d%d",&n,&p);
        puts("1");
        inv[1]=1;
        for(int i=2;i<=n;i++) {
            inv[i]=(ll)p-(p/i)*inv[p%i]%p;
            printf("%lld
    ",inv[i]);
        }
        return 0;
    }
    

    lg T118233 一本通(蓝)P400

  • 相关阅读:
    leetcode-----75. 颜色分类
    《面向机器智能的TensorFlow实践》_段菲学习资料
    事务及其ACID特性
    greenplum基本使用操作
    通过java api统计hive库下的所有表的文件个数、文件大小
    深度学习原理与TensorFlow实践_喻俨资料整理
    采集数据到HDFS
    《深入理解TensorFlow架构设计与实现原理》_彭靖田学习材料整理
    Too many open files
    子元素高度100%
  • 原文地址:https://www.cnblogs.com/ke-xin/p/13692148.html
Copyright © 2020-2023  润新知