您的位置:首页 > 其它

求逆元的几种办法

2016-07-24 20:14 615 查看
补了一道CF题,顺便看到有人求逆元的方法叼叼的,怪不得人家过题这么快啊……

来总结一发……

一般求法

求a关于N的逆元,即要解同余方程ax≡1(modN)的解x.

ax≡1(modN)⇔ax+Ny=1

仅当a与N互质时,存在a的逆元,利用扩展欧几里得求解。

这里N不一定是素数

LL extend_Euclid(LL a, LL b, LL &x, LL &y){
if(b == 0){
x = 1; y = 0;
return a;
}
LL r = extend_Euclid(b, a%b, y, x);
y -= a/b*x;
return r;
}


x = (x % N + N) % N


费马小定理求逆元

当N是素数,有ap−1≡1(modp),则a−1=ap−2%p

当p比较大时,需要快速幂求解。非递归的写法是坠好的。

#define LL long long
LL poo(LL a, int k, int m){
LL res = 1;
while(k){
if(k & 1LL)
res = res * a % m;
k >>= 1;
a = a*a%m;
}
return res;
}


特殊情况

当N是质数,a是(N+1)的约数时,a−1=N+1a

这点也很好理解。当N是质数,0 < a < N时,(a,N)=1,则a肯定存在逆元。

而解出的N+1a就满足N+1a⋅a≡1(modN),故它是a的逆元。

CF 696C,N=1000000007时2−1=1000000007+12=5000000043−1=1000000007+13=333333336求解就灰常方便了…

逆元打表

如果是求好多数的逆元,还是打个表比较方便,只要O(N)。

当N是大素数,求小于N的数的逆元。

设这个数是i,令P=it+k,其中t=i/N, k=i%N

则it≡−k(modP) 且i2t2≡k2(modP)

令i的逆元是i−1,有两种方法求i−1:

i−1≡−t⋅k−1≡(P−t)k−1%P

i−1≡it2(k−1)2%P

都是通过先求k−1来求i−1,两者结果都是一样的,别忘模P即可。注意:计算过程中可能会爆
long long


int rev
;
void get_rev(){
rev[1] = 1;
for(int n = 2;n < N;n++){
int k = P % n, t = P / n;
rev
= 1LL*(P-t)*rev[k]%P;
}
}


暂时只用到了这几种求逆元办法,若还有新的继续更…
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: