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

在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<iostream>
#include<cstring>
#include<cstdio>
#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<len;i++)
            ans=(ans*10+a[i]-'0')%p;
        ans+=p;
        printf("%I64d\n",quickpow(x,ans,z));
    }
    return 0;
}

 

  • 6
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值