• 洛谷 P3811 【模板】乘法逆元(欧拉定理&&线性求逆元)


    题目传送门

    逆元定义

    逆元和我们平时所说的倒数是有一定的区别的,我们平时所说的倒数是指:a*(1/a) = 1,那么逆元和倒数之间的区别就是:假设x是a的逆元,那么 a * x = 1(mod p),也就是只多了一个取余的操作,这个取余的操作,就会保证a的逆元不一定只是a的倒数。那么我们的逆元有什么作用呢?

    并且取余还不满足下面式子:( a/b )%p = (a%p  /  b%p)  %  p ,那么我们如果遇到b过大必须在中间过程进行取余的操作,那么我们会发现在乘法中满足:(a*b) % p = (a%p  *  b%p) %p,那么我们只要将上面式子转换为下面乘法的式子就可以了

    我们用inv(b)来表示b的逆元,那么他一定满足:b*inv(b) = 1(mod p)    ==>  b = 1/inv(b) ,那么我们代入上面的除法的式子:(a/b)%p =     (a * inv(b)) %p = (a%p  *  inv(b)%p) % p

    这样我们就可以根据逆元来将除法取余的式子转换为乘法取余的式子
    原文:https://blog.csdn.net/li1615882553/article/details/80001473

    一:欧拉定理求逆元

     1 #include<iostream>
     2 #include<cstdio>
     3 
     4 using namespace std;
     5 
     6 long long m,k,n,sum,s;
     7 
     8 inline long long phi(long long x) {
     9     long long res = x,a = x;
    10     for(int i = 2;i * i <= a; i++)
    11         if(a % i == 0) {
    12             res = res / i * (i - 1);
    13             while(a % i == 0)
    14                 a = a / i;
    15         }
    16     if(a > 1)
    17         res = res / a * (a - 1);
    18     return res;
    19 }
    20 
    21 inline void _out(long long pp,long long v) {
    22     sum = 1;
    23     while(pp > 0) {
    24         if(pp % 2 != 0)
    25             sum = (sum * v) % m;
    26         pp = pp / 2;
    27         v = (v * v) % m;
    28     }
    29     printf("%d
    ",sum);
    30 }
    31 
    32 int main() {
    33     scanf("%d%d",&n,&m);
    34     k = phi(m);
    35     s = k - 1;
    36     for(int i = 1;i <= n; i++)
    37         _out(s,i);
    38     return 0; 
    39 }
    欧拉定理

    但因为欧拉定理求逆元时间复杂度为O(nlongn),所以本题会被卡两个点。

    二:线性求逆元

     1 #include<iostream>
     2 #include<cstdio>
     3 
     4 using namespace std;
     5 
     6 int n,inv[3000001];
     7 long long p;
     8 
     9 int main() {
    10     inv[1] = 1;
    11     scanf("%d%lld",&n,&p);
    12     for(int i = 2;i <= n; i++) 
    13         inv[i] = (p - p / i) * inv[p % i] % p;
    14     for(int i = 1;i <= n; i++)
    15         printf("%d
    ",inv[i]);
    16     return 0;
    17 }
    线性

    因为是线性,O(n)足够优秀,所以轻松过掉本题

  • 相关阅读:
    DRF
    DRF
    DRF
    DRF
    RESTful介绍
    DRF parser请求处理流程
    Vue项目的创建
    怎么清除file控件的文件路径
    java用spring实现文件下载
    JS判断元素是否在数组内 阿星小栈
  • 原文地址:https://www.cnblogs.com/lipeiyi520/p/11267186.html
Copyright © 2020-2023  润新知