求逆元的几种办法
2016-07-24 20:14
615 查看
补了一道CF题,顺便看到有人求逆元的方法叼叼的,怪不得人家过题这么快啊……
来总结一发……
ax≡1(modN)⇔ax+Ny=1
仅当a与N互质时,存在a的逆元,利用扩展欧几里得求解。
这里N不一定是素数
当p比较大时,需要快速幂求解。非递归的写法是坠好的。
这点也很好理解。当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求解就灰常方便了…
当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即可。注意:计算过程中可能会爆
暂时只用到了这几种求逆元办法,若还有新的继续更…
来总结一发……
一般求法
求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; } }
暂时只用到了这几种求逆元办法,若还有新的继续更…
相关文章推荐
- Linux之防火墙iptables
- 数组复制 System.arraycopy用法例
- Codeforces Round #364 (Div. 2) A - Cards(水)
- LA-5059(组合游戏)
- linux中几个有用的快捷键
- LA 4287 Proving Equivalences(强连通分量缩点)
- webpack及react的搭配使用(一)
- Radar Installation
- 合并两个的排序链表
- Service的绑定中,Binder跨进程与非跨进程的区别
- **ACM集训day12——bfs队列
- hdu4786Fibonacci Tree
- 6位随机密码生成器
- 自己动手实现HTTP协议
- 集合类(一) List的用法测试例
- PAT A1042 Shuffling Machine (20)
- spring-mybatis
- 网站安全认证系统的设计变迁
- JavaSE基础--构造函数
- codeforces--701B Cells Not Under Attack