求逆元的方法汇总

逆元

它是一个可以取消另一给定元素运算的元素。
amax1(mod  m)xam

前提

a(modm),am,

定理

欧拉定理(费马小定理)
  • 欧拉定理: amaφ(m)1(mod  m)

方法

1.欧拉定理

根据欧拉定理

aϕ(m)aaϕ(m)1a111aϕ(m)1(modm)(modm)(modm)

所以 aϕ(m)1a
时间复杂度 O(n) 即求出单个欧拉函数的值
2.exgcd

应用exgcd
我们假设a的逆元是x

axax+my=11(modm)

用exgcd求出x即为a的逆元
时间复杂度 O(loga)
3.需要线性处理1~n的逆元

更正:本方法需在模数为素数情况下才能使用!!!
我们假设 y=ax+b, b<i, 1<x<y
在将这个式子放在 mody  意义下

ax+b0(mody)

两边同时乘上 x1b1 得到
ab1+x1x10ab1(mody)(mody)

再将 y=ax+b 带入得到
x1yx(ymodx)1(mody)

所以我们定义 a[i]xmody 意义下的逆元,根据上式得到
a[i]=(y  div  x)a[ymodx]
1 在模任何意义下逆元都是 1
同时也就得到了一种 O(logN) 级别的递归求单个逆元的方法
由于每次取模,所以每次都相当于折半,复杂度就降到了 O(logN)

最后贴上代码

1.欧拉定理
<code class="hljs oxygene has-numbering"><span class="hljs-keyword">const</span>
    maxn=<span class="hljs-number">1000</span>;
<span class="hljs-keyword">var</span>
    prime:<span class="hljs-keyword">array</span>[<span class="hljs-number">0</span>..maxn]<span class="hljs-keyword">of</span> longint;
    check:<span class="hljs-keyword">array</span>[<span class="hljs-number">0</span>..maxn]<span class="hljs-keyword">of</span> boolean;
    i,j,k:longint;
    n,m,tt,len,ans:longint;
<span class="hljs-function"><span class="hljs-keyword">procedure</span> <span class="hljs-title">prepare</span>;</span>
<span class="hljs-keyword">begin</span>
    len:=<span class="hljs-number">0</span>;
    <span class="hljs-keyword">for</span> i:=<span class="hljs-number">2</span> <span class="hljs-keyword">to</span> trunc(sqrt(maxn)) <span class="hljs-keyword">do</span>
        <span class="hljs-keyword">begin</span>
            <span class="hljs-keyword">if</span> check[i]=<span class="hljs-keyword">false</span>
            <span class="hljs-keyword">then</span> <span class="hljs-keyword">begin</span> inc(len); prime[len]:=i; <span class="hljs-keyword">end</span>;
            <span class="hljs-keyword">for</span> j:=<span class="hljs-number">1</span> <span class="hljs-keyword">to</span> len <span class="hljs-keyword">do</span>
                <span class="hljs-keyword">begin</span>
                    <span class="hljs-keyword">if</span> prime[j]*i>trunc(sqrt(maxn)) <span class="hljs-keyword">then</span> <span class="hljs-keyword">break</span>;
                    check[i*prime[j]]:=<span class="hljs-keyword">true</span>;
                    <span class="hljs-keyword">if</span> i <span class="hljs-keyword">mod</span> prime[j]=<span class="hljs-number">0</span> <span class="hljs-keyword">then</span> <span class="hljs-keyword">break</span>;
                <span class="hljs-keyword">end</span>;
        <span class="hljs-keyword">end</span>;
<span class="hljs-keyword">end</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">f</span><span class="hljs-params">(a,b,m:longint)</span>:</span>longint; <span class="hljs-comment">{a^b mod m}</span>
<span class="hljs-keyword">var</span> t,y:int64;
<span class="hljs-keyword">begin</span>
    t:=<span class="hljs-number">1</span>; y:=a;
    <span class="hljs-keyword">while</span> b<><span class="hljs-number">0</span> <span class="hljs-keyword">do</span>
        <span class="hljs-keyword">begin</span>
            <span class="hljs-keyword">if</span> b <span class="hljs-keyword">and</span> <span class="hljs-number">1</span><><span class="hljs-number">0</span> <span class="hljs-keyword">then</span> t:=(t*y)<span class="hljs-keyword">mod</span> m;
            y:=(y*y)<span class="hljs-keyword">mod</span> m;
            b:=b>><span class="hljs-number">1</span>;
        <span class="hljs-keyword">end</span>;
    <span class="hljs-keyword">exit</span>(t);
<span class="hljs-keyword">end</span>;

<span class="hljs-keyword">begin</span>
    prepare;
    readln(n,m); tt:=m;
    ans:=m;
    <span class="hljs-keyword">for</span> i:=<span class="hljs-number">1</span> <span class="hljs-keyword">to</span> len <span class="hljs-keyword">do</span>
        <span class="hljs-keyword">begin</span>
            <span class="hljs-keyword">if</span> m=<span class="hljs-number">1</span> <span class="hljs-keyword">then</span> <span class="hljs-keyword">break</span>;
            <span class="hljs-keyword">if</span> m <span class="hljs-keyword">mod</span> prime[i]=<span class="hljs-number">0</span> <span class="hljs-keyword">then</span> ans:=(ans <span class="hljs-keyword">div</span> prime[i])*(prime[i]-<span class="hljs-number">1</span>);
            <span class="hljs-keyword">while</span> m <span class="hljs-keyword">mod</span> prime[i]=<span class="hljs-number">0</span> <span class="hljs-keyword">do</span>
                m:=m <span class="hljs-keyword">div</span> prime[i];
        <span class="hljs-keyword">end</span>;
    <span class="hljs-keyword">if</span> m<><span class="hljs-number">1</span> <span class="hljs-keyword">then</span> ans:=(ans <span class="hljs-keyword">div</span> m)*(m-<span class="hljs-number">1</span>);
    writeln(f(n,ans-<span class="hljs-number">1</span>,tt));
<span class="hljs-keyword">end</span>.</code>
2.exgcd
<code class="hljs delphi has-numbering"><span class="hljs-keyword">var</span>
    n,m,a,b,c,x,y:longint;
<span class="hljs-function"><span class="hljs-keyword">procedure</span> <span class="hljs-title">exgcd</span><span class="hljs-params">(a,b:longint; <span class="hljs-keyword">var</span> x,y:longint)</span>;</span>
<span class="hljs-keyword">var</span> c:longint;
<span class="hljs-keyword">begin</span>
    <span class="hljs-keyword">if</span> b=<span class="hljs-number">0</span>
    <span class="hljs-keyword">then</span> <span class="hljs-keyword">begin</span> x:=<span class="hljs-number">1</span>; y:=<span class="hljs-number">0</span>; <span class="hljs-keyword">exit</span>; <span class="hljs-keyword">end</span>
    <span class="hljs-keyword">else</span> exgcd(b,a <span class="hljs-keyword">mod</span> b,x,y);
    c:=x; x:=y; y:=c-(a <span class="hljs-keyword">div</span> b)*x;
<span class="hljs-keyword">end</span>;

<span class="hljs-keyword">begin</span>
    readln(n,m);
    exgcd(n,m,x,y);
    x:=(x+((x <span class="hljs-keyword">div</span> m)+<span class="hljs-number">1</span>)*m+m)<span class="hljs-keyword">mod</span> m;
    writeln(x);
<span class="hljs-keyword">end</span>.
</code>
线性处理1~n
<code class="hljs delphi has-numbering"><span class="hljs-keyword">const</span>
    maxn=<span class="hljs-number">1000</span>;
<span class="hljs-keyword">var</span>
    x:<span class="hljs-keyword">array</span>[<span class="hljs-number">0</span>..maxn]<span class="hljs-keyword">of</span> longint;
    i,j,k:longint;
    n,m:longint;
<span class="hljs-keyword">begin</span>
    readln(n,m);
    x[<span class="hljs-number">1</span>]:=<span class="hljs-number">1</span>;
    <span class="hljs-keyword">for</span> i:=<span class="hljs-number">2</span> <span class="hljs-keyword">to</span> n <span class="hljs-keyword">do</span>
        x[i]:=(-(m <span class="hljs-keyword">div</span> i)*x[m <span class="hljs-keyword">mod</span> i])<span class="hljs-keyword">mod</span> m;
    writeln(x[i]);
<span class="hljs-keyword">end</span>.    </code>
线性处理转求单个
<code class="hljs actionscript has-numbering"><span class="hljs-keyword">var</span>
    n,m:longint;
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">f</span><span class="hljs-params">(a:longint)</span><span class="hljs-type">:longint</span>;</span>
begin
    <span class="hljs-keyword">if</span> a=<span class="hljs-number">1</span>
    then exit(<span class="hljs-number">1</span>)
    <span class="hljs-keyword">else</span> exit((-(m div a)*f(m mod a))mod m);
end;

begin
    readln(n,m);
    writeln(f(n));
end.</code>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值