zoukankan      html  css  js  c++  java
  • 洛谷 P3811 【模板】乘法逆元

    传送门


    逆元

    什么是逆元?

    首先取模运算在加法、减法、乘法中是满足分配率的,即
    ((a+b)\%p=(a\%p+b\%p)\%p)
    ((a*b)\%p=((a\%p)*(b\%p))\%p)
    但是除法却不满足。
    而有时候(frac{b}{a}\%p)中分子和分母都特别大,需要在计算过程中取模,这时候就需要把其转化成
    (b*x\%p),其中x叫做a在模p意义下的逆元。即
    (a*xequiv 1pmod p)

    怎么求逆元?

    1. 费马小定理
      当a、p互质时,
        (a^{p-1}equiv1pmod p)
      即 (a*a^{p-2}equiv1pmod p)
      可以看出,此时(a^{p-2})即为a的逆元。
      可以快速幂求出。

    2. exgcd
      直接根据同余方程(a*xequiv 1pmod p)exgcd求解即可。

    3. 线性递推
      用于求 1~n 在%p意义下的逆元。
      设p=k*i+r,则(k*i+requiv0pmod p)
      然后把等式两边同时乘i和r的逆元((x^{-1})表示x的逆元):
      (k*i*i^{-1}*r^{-1}+r*i^{-1}*r^{-1}equiv0pmod p)
      化简得:
      (k*r^{-1}+i^{-1}equiv0pmod p)
      再移项可得:
      (i^{-1}equiv -k*r^{-1}pmod p)
      把k替换成p/i,r替换成p%i,可以得出递推公式:
      (inv[i]=-(p/i)*inv[p\%i]\%p)
      注意逆元为正数,所以(inv[i]=(inv[i]+p)\%p)

    AC代码

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<ctime>
    using namespace std;
    int n,p,inv[3000005];
    int main(){
    	cin>>n>>p; 
    	inv[1]=1;
    	printf("1
    ");
    	for(int i=2;i<=n;i++) {
    		inv[i]=((-(1ll)*(p/i)*inv[p%i])%p+p)%p;
    		printf("%d
    ",inv[i]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    java中变量、对象的存储
    悬停小组件-反馈和返回顶部
    setTimeout、setInternal传递带参数的函数
    jquery绑定事件时如何传递参数
    jQuery判断复选框checkbox是否选中
    bootstrap模态框垂直居中显示
    【转】Spring事务的隔离级别
    第一天 纪念下下
    羊车门
    关于Python课程的一些思考。
  • 原文地址:https://www.cnblogs.com/yinyuqin/p/14773781.html
Copyright © 2011-2022 走看看