逆元
它是一个可以取消另一给定元素运算的元素。
对于正整数a和m,如果有a⋅x≡1(mod m),那么把这个同余方程中x的最小正整数解叫做a模m的逆元。
前提
求 a(modm)意义下的逆元,要求a与m互质,否则不存在乘法逆元
定理
欧拉定理(费马小定理)
- 欧拉定理: 若a与m互质,那么有aφ(m)≡1(mod m)
方法
1.欧拉定理
根据欧拉定理
aϕ(m)a⋅aϕ(m)−1a−1≡≡≡11aϕ(m)−1(modm)(modm)(modm)
所以 aϕ(m)−1为a的逆元
时间复杂度 O(n−−√) 即求出单个欧拉函数的值
2.exgcd
应用exgcd
我们假设a的逆元是x
a⋅xa⋅x+m⋅y≡=11(modm)
用exgcd求出x即为a的逆元
时间复杂度 O(loga)
3.需要线性处理1~n的逆元
更正:本方法需在模数为素数情况下才能使用!!!
我们假设
y=a⋅x+b, b<i, 1<x<y
在将这个式子放在
mody
意义下
a⋅x+b≡0(mody)
两边同时乘上 x−1⋅b−1 得到
a⋅b−1+x−1x−1≡≡0−a⋅b−1(mody)(mody)
再将 y=a⋅x+b 带入得到
x−1≡−⌊yx⌋⋅(ymodx)−1(mody)
所以我们定义 a[i]为x的mody 意义下的逆元,根据上式得到
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>