标签:约数 exp line include void math += 裴蜀定理 存在
目录
本文章内,若无特殊说明,数字指的是整数,除法指的是整除。
我们称\(a\)是\(b\)在模\(p\)情况下的逆元,则有\(a \times b \equiv 1 ( mod\,\,p)\)。
所以呢,我们其实可以将逆元看成一个数的相反数。所以在除以一个数的时候,就相当于乘上它的相反数。
我们先来看看什么情况下有逆元。
当且仅当\(gcd(b,p)=1\)时,\(b\)在模\(p\)情况下有逆元。
这个结论可由裴蜀定理显然推得,下面一段来自百度百科,若读者对证明有兴趣,可以自行了解。
裴蜀定理(或贝祖定理,Bézout‘s identity)得名于法国数学家艾蒂安·裴蜀,说明了对任何整数\(a\)、\(b\)和它们的最大公约数\(d\),关于未知数\(x\)和\(y\)的线性不定方程(称为裴蜀等式):若\(a\),\(b\)是整数,且\((a,b)=d\),那么对于任意的整数\(x\),\(y\),\(ax+by\)都一定是\(d\)的倍数,特别地,一定存在整数\(x\),\(y\),使\(ax+by=d\)成立。
下面介绍如何用拓展欧几里得求逆元。
我们求\(b\)在模\(g\)意义下的逆元,根据\(a \times b \equiv 1 ( mod\,\,p)\),得到\(a\times b + k\times p = 1\)。
我们知道,\(gcd(b,p)=gcd(p,b \% p)\),所以\(a'\times p+k'\times (b \% p)=1\)同样有解。而由于\(gcd(b,p)=1\),辗转相除法时,总有\(a''\times 1 + k'' \times 0 = 1\)。
此时我们不妨令\(a''=1,k''=0\)。
现在我们考虑怎么推回去。
\[
a'\times p+k'\times (b \% p)=1
\]
\[
\Rightarrow a'\times p+k'\times( b-\frac{b}{p}\times p)=1
\]
\[
\Rightarrow k'\times b+(a'-\frac{b}{p}\times k') \times p=1
\]
与\(a\times b + k\times p = 1\)对照,得到\(a=k',\,\,\,k=a'-\frac{b}{p}\times k'\)。那么这样,我们就得到了\(a\times b + k\times p = 1\)的一组解,同时,\(a\)就是\(b\)在模\(p\)下的逆元。
附C++程序
#include <bits/stdc++.h>
using namespace std;
void ExPower( int b, int p, int & a, int & k ) {
if( p == 0 ) {
a = 1; k = 0;
return;
}
ExPower( p, b % p, k, a );
k -= b / p * a;
return;
}
int main() {
int b, p;
cin >> b >> p;
int a, k;
ExPower( b, p, a, k );
if( a < 0 ) a += p;
cout << a << endl;
return 0;
}
如果我们需要求\(0!\)到\(n!\)的逆元,对于每个元素都求一遍,就显得有点慢。(虽然\(exPower\)的时间快到可以认为是小常数。)
前面我们说了,逆元就可一看做是求倒数。那么不就有\(\frac{1}{(n+1)!}\times (n+1)=\frac{1}{n!}\)。
附C++程序:
int inv( int b, int p ) {
int a, k;
exPower( b, p, a, k );
if( a < 0 ) a += p;
return a;
}
void init( int n ) {
Fact[ 0 ] = 1;
for( int i = 1; i <= n; ++i ) Fact[ i ] = Fact[ i - 1 ] * i % Mod;
INV[ n ] = inv( Fact[ n ], Mod );
for( int i = n - 1; i >= 0; --i ) INV[ i ] = INV[ i + 1 ] * ( i + 1 ) % Mod;
return;
}
标签:约数 exp line include void math += 裴蜀定理 存在
原文地址:https://www.cnblogs.com/chy-2003/p/9656801.html