• 逆元


    一、扩展欧几里得求逆元

      逆元的定义即是对于a,满足a*x≡1(mod b),就把x称作a在模b意义下的逆元,而扩展欧几里得可以就线性同余方程,这里显然适用。

    二、快速幂求逆元

      这里用到了费马小定理和欧拉定理。

      费马小定理:对于素数p,有ap-1≡1(mod p)

      证明:首先根据同余的性质,我们可知若a≡b(mod m),则a*c≡b*c(mod m)

        ∴我们对于素数p的剩余系:1,2,3,4...p-1中的两个数x,y

         有a*x≡a*y(mod p)必定不成立,因为p为素数,所以可以约去a,得到x=y,这显然不成立

        ∴1,2,3,4...p-1和a,2a,3a,4a...(p-1)a形成映射

        ∴(p-1)!≡(p-1)!ap-1(mod p)

        ∴约去(p-1)!,得ap-1≡1(mod p)

      欧拉定理:对于任意互质正整数a,n,满足aΦ(n)≡1(mod n)

      证明:与费马小定理类似,只是将剩余系改为小于n与n互质的数。

    三、线性递推(递归)

      对于i在模p意义下的逆元,我们可以用假设p=k*i+r(r<i),因此显然:k*i+r≡0(mod p)

      而将等式两边同时乘上i-1和r-1得到:k*r-1+i-1≡0(mod p),移项后为i-1≡-k*r-1(mod p)

      因此i-1≡-(p div i)*(p mod i)-1(mod p)

      所以递推式为inv[i]=-(p/i)*inv[p%i]

    四、阶乘逆元

      显然对于阶乘n!的逆元为,所以阶乘逆元的递推公式即为inv[i]=inv[i+1]*(i+1)

    例1:Sumdiv

      求出ab的所有约数的和模9901的值。

      这道题实际上就是让我们求(1+p1+p12+...+p1r1)(1+p2+p22+...+p2r1)...(1+pn+pn2+...+pnrn

      而对于每个素数的分解我们可以直接通过枚举因数得到,但我们还需要快速求每个因数的和。

      方法一:对于每个求和,我们根据r的奇偶性分类,可以不断递归求解,递归式如下:

          ①若n为奇数,cal(p,n)=cal(p,n/2)×(1+pn/2+1

          ②若n为偶数,cal(p,n)=cal(p,n/2-1)×(1+pn/2+1)+pn/2

      方法二:直接运用等比数列求和公式

      代码

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    const ll N=1000000; 
    const ll mod=9901;
    
    ll prime[N],r[N]; 
    ll qpow(ll a,ll b)
    {
        ll res=1;
        for(;b;b>>=1)
        {
            if(b&1)res=res*a%mod;
            a=a*a%mod;
        }
        return res;
    }
    ll cal(ll p,ll n)
    { 
        if(!n)return 1;
        if(n&1)
            return cal(p,n>>1)*(1+qpow(p,(n>>1)+1))%mod;
        else return (cal(p,(n>>1)-1)*(1+qpow(p,(n>>1)+1))%mod+qpow(p,n>>1))%mod;
    }
    
    int main()
    {
        ll a,b,cnt=0;
        scanf("%lld%lld",&a,&b);
        for(ll i=2;i<=sqrt(a);i++)
            if(!(a%i))
            {
                prime[++cnt]=i;
                while(!(a%i))r[cnt]++,a/=i;
            }
        if(a!=1)prime[++cnt]=a,r[cnt]=1;
        ll ans=1;
        for(ll i=1;i<=cnt;i++)
            ans=ans*cal(prime[i],r[i]*b)%mod;
        printf("%lld",ans);
    }
  • 相关阅读:
    TWaver HTML5 (2D)--基本概念
    浏览器编码的函数简介escape(),encodeURI(),encodeURIComponent()
    pom.xml
    注解式控制器简介
    Controller接口
    WebContentGenerator
    Controller简介
    DispatcherServlet中使用的特殊的Bean
    DispatcherServlet默认配置
    DispatcherServlet
  • 原文地址:https://www.cnblogs.com/fangbozhen/p/11735303.html
Copyright © 2020-2023  润新知