逆元:
又称数论倒数,实质为倒数的扩展。
对于取mod,我们知道:
(a + b) % p = (a%p + b%p) %p
(a - b) % p = (a%p - b%p) %p——(a - b) % p = (a%p - b%p + p) %p 防止出现负数
(a * b) % p = (a%p * b%p) %p
但是对于除法类似的规则并不适用(可以自行举例验证)。
那么我们该如何对存在除法操作的算式取mod呢?
这时就需要逆元了。
定义:如果 ax = 1(mod p),那么称a和x互为mod c意义下的逆元。
当且仅当gcd(a,p)==1即a,p互质时,
对于一个数a的逆元,我们用inv(a)表示
这样对于(a / b) % p = (a * inv(a) ) % p = (a % p * inv(a) % p) % p、
求解逆元的方法:
费马小定理求逆元:只适用于模数为质数,且模数与欲求逆元的数互质。
详解:http://blog.youkuaiyun.com/qq_36693533/article/details/78412892
代码
ll powr(ll a,ll b)
{
if(!b)
return 1;
ll temp=powr(a,b>>1);
temp=temp*temp%mod;
if(b&1)
temp=temp*a%mod;
return temp%mod;
}
inv[i]=powr(i,mod-2);
扩展欧几里得求逆元:只适用于模数与欲求逆元数互质的情况,但对模数是否为质数没有要求。详解见下方扩展欧几里得内容。
代码
ll exgcd(ll a,ll b,ll &x,ll &y)
{
if(b==0)
{
x=1;
y=0;
return a;
}
ll d=exgcd(b,a%b,x,y);
ll tmp=x;
x=y;
y=tmp-a/b*y;
return d;
}
exgcd(i,p,x,y);
inv[i]=x;
欧拉定理求逆元…只适用于模数与欲求逆元数互质的情况,但对模数是否为质数没有要求…但我不太会。
注意,以上三种求逆元的方式都一个共同的前提——模数与欲求逆元数互质,这也逆元存在的前提。那么对于模数与欲求数不互质的情况呢?一种方法是递推求,这个时候求的东西就不再是逆元了,将在下方介绍。
还有一种方法是用除法取模的公式….通过公式的转化直接避免除法取模。
公式使用条件:b|a即b整除a
证明:
(a/b)mod m = ans ;
a/b = ans + k * m ;
a = ans * b + k * m * b ;
a mod ( bm ) = ans * b ;
a mod ( bm ) / b = ans ;
递推求1-n在模p(p>n且p为奇质数)意义下的逆元:
inv[i] = (p - p/i)* inv[p % i] % p
另外有结论:1-p在mod p意义下的所有逆元对应1-p-1中的所有数。例如当p=7时,1-6的逆元为1 , 4 , 5 , 2 , 3 , 6,对应1-6中的数。
代码
inv[1]=1;
for(int i=2;i<=n;++i)
inv[i]=(p-p/i)*inv[p%i]%p;
最大公因数gcd和最小公倍数lcm:
代码
ll gcd(ll a,ll b)
{
return b==0?a:gcd(b,a%b);
}
ll lcm(ll a,ll b)
{
//return a