三种求乘法逆元方法详解
来源:互联网 发布:sql identity是什么 编辑:程序博客网 时间:2024/05/19 16:05
题目背景
这是一道模板题
题目描述
给定n,p求1~n中所有整数在模p意义下的乘法逆元。
输入输出格式
输入格式:
一行n,p
输出格式:
n行,第i行表示i在模p意义下的逆元。
输入输出样例
10 13
179108112534
说明
1≤n≤3×106,n<p<20000528
输入保证 p 为质数。
我们有三种办法求逆元
由欧拉定理可知
当gcd(a,n)==1 时 我们有 Aφ(n-1)≡ 1(mod n) ;
所以 我们有 A*Aφ(n-2) ≡ 1(mod n)
所以Aφ(n-2) 就是A关于mod n的逆元
1 /* 2 p为素数时 可用费马小定理 3 longlong*longlong 要慢一点 66分 4 */ 5 #include <cctype> 6 #include <cstdio> 7 8 typedef long long LL; 9 10 int n,p;11 12 inline LL quick_pow(LL a,int k) {13 LL ret=1;14 while(k) {15 if(k&1) ret=(ret*a)%p;16 k>>=1;17 a=(a*a)%p;18 }19 return ret;20 }21 22 int hh() {23 scanf("%d%d",&n,&p);24 printf("1\n");25 for(int i=2;i<=n;++i) {26 LL t=quick_pow(i,p-2);27 printf("%d\n",(t+p)%p);28 }29 return 0;30 }31 32 int sb=hh();33 int main(int argc,char**argv) {;}
还有我们可以用exgcd来求逆元
我们知道 若ax≡1(mod p) 这我们可以写成 ax=py+1;
移项则有 ax-by=1 这明显就是扩展欧几里得
当 ax+by=gcd(a,b) gcd(a,b) == gcd(b,a%b)
我们得到 bx1+(a-a/b)y1=gcd(b,a%b);
则 ax+by=bx1+(a-(a/b)*b)y1 //这里 / 代表整除
ax+by=bx1+ay1-b*(a/b)y1
ax+by=ay1+b(x1-(a/b)*y1)
我们得到 x=y1
y=x1-(a/b)*y1;
x 即为我们所求的逆元
由于 x 可能为负数 要(x+p)%p
1 /* 2 EXgcd 求逆元 3 比费马小定理要快一点 83分 4 */ 5 #include <cstdio> 6 #include <cctype> 7 8 int n,p; 9 10 inline int exgcd(int a,int b,int&x,int&y) {11 if(!b) {12 x=1;y=0;13 return a;14 }15 int p=exgcd(b,a%b,x,y);16 int t=x;17 x=y;18 y=t-(a/b)*y;19 return p;20 } 21 22 int hh() {23 scanf("%d%d",&n,&p);24 printf("1\n");25 int x,y; 26 for(int i=2;i<=n;++i) {27 exgcd(i,p,x,y);28 printf("%d\n",(x+p)%p);29 }30 return 0;31 }32 33 int sb=hh();34 int main(int argc,char**argv) {;}
但是对于 这个题来讲 复杂度还是不够
我们还有线性求逆元的方法
来看带余除法 式子 p=k*i+r
我们可以写成 k*i+r≡0(mod p)
式子两边同乘 i-1*r-1 (i-1,r-1皆为模p意义下的逆元)
所以我们有 k*r-1+i-1≡0(mod p)
i-1≡-k*r-1(mod p)
i-1≡-(p/i)*(p%i)-1(mod p)
这样我们就线性求得了逆元
1 #include <cctype> 2 #include <cstdio> 3 4 typedef long long LL; 5 const int MAXN=3000010; 6 7 int n,p; 8 9 LL inv[MAXN];10 11 int hh() {12 scanf("%d%d",&n,&p);13 printf("1\n");14 inv[1]=1;15 for(int i=2;i<=n;++i) {16 inv[i]=(LL)(p-p/i)*inv[p%i]%p;17 printf("%d\n",inv[i]);18 }19 return 0;20 } 21 22 int sb=hh();23 int main(int argc,char**argv) {;}
- 三种求乘法逆元方法详解
- 详解--乘法逆元
- 3种方法求乘法逆元
- 乘法逆元
- 乘法逆元
- 关于乘法逆元
- 乘法逆元
- 乘法逆元
- 乘法逆元
- 求乘法逆元
- 求乘法逆元
- 乘法逆元
- 乘法逆元
- 乘法逆元
- 乘法逆元
- 乘法逆元
- 乘法逆元基础知识
- 乘法逆元
- 51Nod 1453 抽彩球
- 1806: [Ioi2007]Miners 矿工配餐
- P2424 约数和
- UVa 11440 Help Tomisu 欧拉函数
- UVa 1575 Factors
- 三种求乘法逆元方法详解
- P1463 [SDOI2005]反素数ant
- cocos2d Anroid 打包Apk
- 【NOIP2016】蚯蚓 --队列模拟
- 1624 取余最长路 (前缀和+set二分)
- P1118 [USACO06FEB]数字三角形Backward Digit Su…
- 1640 天气晴朗的魔法
- 51Nod 1378 夹克老爷的愤怒
- 1737 配对