最新消息: USBMI致力于为网友们分享Windows、安卓、IOS等主流手机系统相关的资讯以及评测、同时提供相关教程、应用、软件下载等服务。

【逆元】

IT圈 admin 39浏览 0评论

【逆元】

逆元(inv)

1.什么是逆元

当求解公式:(a/b)%m 时,因b可能会过大,会出现爆精度的情况,所以需变除法为乘法:

设c是b的逆元,则有b*c≡1(mod m);

则(a/b)%m = (a/b)*1%m = (a/b)*b*c%m = a*c(mod m);

即a/b的模等于a*b的逆元的模;

逆元就是这样应用的;


2.求逆元的方法

(1).费马小定理

在  p  是素数的情况下,对任意整数  x  都有  xp≡x(mod)p  。 
如果  x  无法被  p  整除,则有  xp−1≡1(modp)  。 
可以在  p  为素数的情况下求出一个数的逆元,  x∗xp−2≡1(modp)  ,  xp−2  即为逆元。

题目中的数据范围1<=x<=10^9,p=1000000007,p是素数;

所以x肯定就无法被p整除啊,所以最后就得出x^(p-2)为x的逆元啦。

复杂度O(logn);

代码:

const int mod = 1000000009;
long long quickpow(long long a, long long b) {if (b < 0) return 0;long long ret = 1;a %= mod;while(b) {if (b & 1) ret = (ret * a) % mod;b >>= 1;a = (a * a) % mod;}return ret;
}
long long inv(long long a) {return quickpow(a, mod - 2);
}

(2)扩展欧几里得算法求逆元

扩展欧几里得算法可以参考小白书;

百度百科-乘法逆元中有这样一个例子:

例如:4关于1模7的乘法逆元为多少? 4X≡1 mod 7 这个方程等价于求一个X和K,满足 4X=7K+1 其中X和K都是整数。 求x,k就是扩展欧几里得算法了吧~

可扩展欧几里得求逆元ax≡1(mod n)其中a,n互质;

复杂度:O(logn);

代码:

ll extend_gcd(ll a, ll b, ll &x, ll &y) {if (b == 0) {x = 1, y = 0;return a;}else {ll r = extend_gcd(b, a % b, y, x);y -= x * (a / b);return r;}
}
ll inv(ll a, ll n) {ll x, y;extend_gcd(a, n, x, y);x = (x % n + n) % n;return x;
}


(3) 逆元线性筛 ( P为质数 )

求1,2,...,N关于P的逆元(P为质数)

复杂度:O(N)

代码:

const int mod = 1000000009;
const int maxn = 10005;
int inv[maxn];
inv[1] = 1;
for(int i = 2; i < 10000; i++)inv[i] = inv[mod % i] * (mod - mod / i) % mod;

如果是求阶乘的逆元呢?(阶乘数组:fac[ ])

代码:

inv[maxn]=mod_pow(fac[maxn],mod-2);
for(ll i=maxn-1;i>=0;i--)inv[i]=(inv[i+1]*(i+1))%mod;






参考blog:

.html、

/%E9%80%86%E5%85%83.html。

【逆元】

逆元(inv)

1.什么是逆元

当求解公式:(a/b)%m 时,因b可能会过大,会出现爆精度的情况,所以需变除法为乘法:

设c是b的逆元,则有b*c≡1(mod m);

则(a/b)%m = (a/b)*1%m = (a/b)*b*c%m = a*c(mod m);

即a/b的模等于a*b的逆元的模;

逆元就是这样应用的;


2.求逆元的方法

(1).费马小定理

在  p  是素数的情况下,对任意整数  x  都有  xp≡x(mod)p  。 
如果  x  无法被  p  整除,则有  xp−1≡1(modp)  。 
可以在  p  为素数的情况下求出一个数的逆元,  x∗xp−2≡1(modp)  ,  xp−2  即为逆元。

题目中的数据范围1<=x<=10^9,p=1000000007,p是素数;

所以x肯定就无法被p整除啊,所以最后就得出x^(p-2)为x的逆元啦。

复杂度O(logn);

代码:

const int mod = 1000000009;
long long quickpow(long long a, long long b) {if (b < 0) return 0;long long ret = 1;a %= mod;while(b) {if (b & 1) ret = (ret * a) % mod;b >>= 1;a = (a * a) % mod;}return ret;
}
long long inv(long long a) {return quickpow(a, mod - 2);
}

(2)扩展欧几里得算法求逆元

扩展欧几里得算法可以参考小白书;

百度百科-乘法逆元中有这样一个例子:

例如:4关于1模7的乘法逆元为多少? 4X≡1 mod 7 这个方程等价于求一个X和K,满足 4X=7K+1 其中X和K都是整数。 求x,k就是扩展欧几里得算法了吧~

可扩展欧几里得求逆元ax≡1(mod n)其中a,n互质;

复杂度:O(logn);

代码:

ll extend_gcd(ll a, ll b, ll &x, ll &y) {if (b == 0) {x = 1, y = 0;return a;}else {ll r = extend_gcd(b, a % b, y, x);y -= x * (a / b);return r;}
}
ll inv(ll a, ll n) {ll x, y;extend_gcd(a, n, x, y);x = (x % n + n) % n;return x;
}


(3) 逆元线性筛 ( P为质数 )

求1,2,...,N关于P的逆元(P为质数)

复杂度:O(N)

代码:

const int mod = 1000000009;
const int maxn = 10005;
int inv[maxn];
inv[1] = 1;
for(int i = 2; i < 10000; i++)inv[i] = inv[mod % i] * (mod - mod / i) % mod;

如果是求阶乘的逆元呢?(阶乘数组:fac[ ])

代码:

inv[maxn]=mod_pow(fac[maxn],mod-2);
for(ll i=maxn-1;i>=0;i--)inv[i]=(inv[i+1]*(i+1))%mod;






参考blog:

.html、

/%E9%80%86%E5%85%83.html。

发布评论

评论列表 (0)

  1. 暂无评论