• P3811 【模板】乘法逆元


    题目背景

    这是一道模板题

    题目描述

    给定n,p求1~n中所有整数在模p意义下的乘法逆元。

    输入输出格式

    输入格式:

    一行n,p

    输出格式:

    n行,第i行表示i在模p意义下的逆元。

    输入输出样例

    输入样例#1: 复制
    10 13
    输出样例#1: 复制
    1
    7
    9
    10
    8
    11
    2
    5
    3
    4

    说明

    1 leq n leq 3 imes 10 ^ 6, n < p < 200005281n3×106,n<p<20000528

    输入保证 pp 为质数。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    namespace Exgcd
    {
        int n,mod,x,y;
        
        void exgcd(int a,int b,int &x,int &y)
        {
            if(b==0)
            {
                x=1,y=0;
                return;
            }
            exgcd(b,a%b,y,x);//回代
            y-=a/b*x;
        }
        
        void work()
        {
            scanf("%d%d",&n,&mod);//求n关于mod的逆元
            exgcd(n,mod,x,y);
            printf("%d
    ",(x+mod)%mod);
        }
    }
    
    namespace Euler_Fermat
    {
        /*————————费马小定理(模数为素数)    O(log n)———————— 
        
        在p是素数的情况下,对任意整数x都有x^p≡x(mod p)。
        如果x无法被p整除,则有x^(p-1)≡1(modp)。
        可以在p为素数的情况下求出一个数的逆元,x*x(p-2)≡1(mod p),x(p-2)即为逆元。
        在模为素数p的情况下,有费马小定理
        a^(p-1)=1(mod p)
        那么a^(p-2)=a^-1(mod p)
        也就是说a的逆元为a^(p-2)
        
        而在模不为素数p的情况下,有欧拉定理
        a^phi(m)=1(mod m)
        同理a^-1=a^(phi(m)-1)
        
        因此逆元x便可以套用快速幂求得了x=a^(phi(m)-1)
        
        若已知p为素数,则直接快速幂求逆元x=a^p-2,
        否则求出a的phi值,快速幂求逆元x=a^(phi-1) 
        
        */
        
        int n,mod;
        
        int euler_phi(int n)
        {
            int res=n;
            for(int i=2;i*i<=n;i++)
            {
                if(n%i==0)
                {
                    res=res/i*(i-1);
                    while(n%i==0)
                        n/=i;
                }
            }
            if(n!=1)
                res=res/n*(n-1);
            return res;
        }
        
        int ksm(int n,int k)
        {
            int ans=1,tmp=n;
            while(k)
            {
                if(k&1) ans=ans*tmp,ans%=mod;
                tmp*=tmp,tmp%=mod;
                k>>=1;
            }
            return ans;
        }
        
        void work()
        {
            scanf("%d%d",&n,&mod);
            printf("%d
    ",ksm(n,mod-2));    //p为素数 
            int phi=euler_phi(mod);    //求phi值 
            printf("%d
    ",ksm(n,phi-1));
        }
    }
    
    namespace Recursion
    {
        /*——————————O(n)求逆元表    模数为素数———————— 
        
        有时会遇到这样一种问题,
        在模质数p下,求1~n逆元 n< p
        
        这个问题有种很牛的算法,其基于以下的推导:
        在求i的逆元时
        p%i+[p/i]*i=p
        令a=p%i,b=[p/i],则有
        a+b*i=p
        a+b*i=0(mod p)
        b*i=-a(mod p)
        i^-1=-b/a
        也就是说i的逆元为:-[p/i]*(p%i)^-1
        而p%i<i,那么可以从2递推到n求逆元,在求i之前p%i一定已经求出
        这样就可以O(n)求出所有逆元了 
    
        */
        
        const int N=3000005;
        
        int n,mod;
        int inv[N];
        
        void work()
        {
            scanf("%d%d",&n,&mod);
            inv[1]=1;
            for(int i=2;i<=n;++i)
                inv[i]=1LL*(mod-mod/i)*inv[mod%i]%mod;
            for(int i=1;i<=n;++i)
                printf("%d
    ",inv[i]);
        }
        
    }
    
    int main()
    {
        Exgcd::work();
        Euler_Fermat::work();
        Recursion::work();
    }
  • 相关阅读:
    JSP基础语法
    MySQL数据库_数据的增删改查
    [数据库] windows server 2003下mysql出现10048错误的解决办法 Can't connect to MySQL server on '127.0.0.1' (10048)(抄)
    支持onvif的摄像机,可以通过onvif工具来设置预置位,odm工具
    word里面对齐用Tab键
    Plctext 如何发送默认的模式
    关于TVWALL 通过AS300获取状态连接失败
    测试人员需要了解的测试工具(转)
    国内可用的Internet时间同步服务器地址(NTP时间服务器) 好在阿里云提供了7个NTP时间服务器也就是Internet时间同步服务器地址(转)
    修改MAC地址的方法 破解MAC地址绑定(抄)
  • 原文地址:https://www.cnblogs.com/lovewhy/p/8742682.html
Copyright © 2020-2023  润新知