求逆元
来源:互联网 发布:医生转行 知乎 编辑:程序博客网 时间:2024/05/17 23:15
求逆元
第一种方法:扩展欧几里得法
/*扩展欧几里得法(求ax+by=gcd)返回d=gcd(a,b);和对应等式ax+by=d中的x、y*/typedef long long ll;ll extendGcd(ll a,ll b,ll &x,ll &y){ if(a==0&&b==0) { return -1; } if(b==0) { x=1; y=0; return a; } ll d=extendGcd(b,a%b,y,x); y-=a/b*x; return d;}//求逆元ax=1(mod n)ll modReverse(ll a,ll n){ ll x,y; ll d=extendGcd(a,n,x,y); if(d==1) return (x%n+n)%n; else return -1;//表示无逆元}
第二种方法:简洁写法
/*求逆元的简洁写法只能求a<m的情况,且a与m互质求ax=1(mod m)的x的值,即逆元(0<a<m)*/typedef long long ll;ll inv(ll a,ll m){ if(a==1) return 1; return inv(m%a,m)*(m-m/a)%m;}
第三种:欧拉函数求逆元(费马小定理)
逆元的几种求法(扩展欧几里得,费马小定理或欧拉定理,特例,打表等)
/*欧拉函数法mod为素数,而且a和m互质*///快速幂取模ll powM(ll a,ll b,ll m){ ll tmp=1; if(b==0)return 1; if(b==1)return a%m; tmp=powM(a,a>>1,m); tmp=tmp*tmp%m; if(b&1) { tmp=tmp*a%m; } return tmp;}ll inv(ll a,ll m){ return powM(a,m-2,m);}
第四种:求阶乘逆元
typedef long long ll;const ll MOD = 1e9 + 7; // 必须为质数才管用const ll MAXN = 1e5 + 3;ll fac[MAXN]; // 阶乘ll inv[MAXN]; // 阶乘的逆元ll QPow(ll x, ll n){ ll ret = 1; ll tmp = x % MOD; while (n) { if (n & 1) { ret = (ret * tmp) % MOD; } tmp = tmp * tmp % MOD; n >>= 1; } return ret;}void init(){ fac[0] = 1; for (int i = 1; i < MAXN; i++) { fac[i] = fac[i - 1] * i % MOD; } inv[MAXN - 1] = QPow(fac[MAXN - 1], MOD - 2); for (int i = MAXN - 2; i >= 0; i--) { inv[i] = inv[i + 1] * (i + 1) % MOD; }}