常见的几种求模运算(mod)——加减乘、除的小费马定理、指数的欧拉降幂

2019-04-13 15:29发布

在C/C++中,+,-的优先级低于/,*,%,而/,*,%优先级一样,所以就从左到右

1.乘法

我们在做题的时候,遇到(a*b)%c,由于可能a*b先计算的话,会超精度,所以我们可以这么转化 (a*b)%c = (a%c)*(b%c)%c  

2.加法或减法

(a+b)%c =( (a%c)+(b%c) )%c  

3.除法

我们一般遇到除法 (a/b)%MOD的时候,会将除法变为乘法,用到了“逆元”的思想 什么是逆元: 当求解公式:(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的逆元的模; 逆元就是这样应用的;   如何求逆元: 一个简单的方法,用小费马定理,具体不讲,就讲如何计算,先找一个素数,一般题目给出的最后答案需要对某个数(1e9+7)进行求模,这个数刚好就是素数,所以就用这个MOD 那么对于某个数的逆元,如b的逆元就是b^(MOD-2),这个计算就用到了快速幂来计算。 所以对于: (a/b)%MOD = (a*b^{MOD-2})%MOD 这样子就把除法的求模运算,变成了乘法的求模运算  

4.大指数——欧拉降幂(具体会模板,知道怎么用)

当遇到,比如10^100000,指数爆炸的时候就要降幂,因此需要用到“欧拉降幂”,具体原理可点击:欧拉函数与欧拉降幂 直接讲结论和代码模板(要结合快速幂),根据一道题来:FZU 1759 简单题意就是,A^B mod C,其中B很大,B<10^100000,那么这个指数就会爆炸,所以就要利用欧拉降幂,代码中phi()函数表示欧拉函数,quickpow()函数表示快速幂。 代码如下: #include #include #include #define ll __int64 #define mod 10000000007 using namespace std; char a[1000006]; ll x,z; ll quickpow(ll x,ll y,ll z) { ll ans=1; while(y) { if(y&1) ans=ans*x%z; x=x*x%z; y>>=1; } return ans; } ll phi(ll n) { ll i,rea=n; for(i=2;i*i<=n;i++) { if(n%i==0) { rea=rea-rea/i; while(n%i==0) n/=i; } } if(n>1) rea=rea-rea/n; return rea; } int main() { while(scanf("%I64d %s %I64d",&x,a,&z)!=EOF) { ll len=strlen(a); ll p=phi(z); ll ans=0; for(ll i=0;i