洛谷

类似的因为模数比较小的坑还有卢卡斯定理那道,也是有时候逆元会不存在,因为整除了。使用一些其他方法避免通过逆元。

https://www.luogu.org/fe/problem/P1593
有坑。一定要好好理解费马小定理等逆元存在的条件。费马小定理求逆元的条件是p是质数且a不为0,扩展欧几里得算法的条件是a,m互质。
那么上面用费马小定理求等比数列的分母的逆元的时候,就没有判断a不为0。而他们也不互质所以也不能使用扩展欧几里得算法。
其实当a为0的时候这个退化为等差数列。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int mod=9901;

ll a,b;
ll factor[100][2];
int ftop=0;

void fj() {
    for(ll i=2; i*i<=a; i++) {
        if(a%i==0) {
            ftop++;
            factor[ftop][0]=i;
            factor[ftop][1]=0;
            while(a%i==0) {
                factor[ftop][1]++;
                a/=i;
            }
        }
    }
    if(a!=1) {
        ftop++;
        factor[ftop][0]=a;
        factor[ftop][1]=1;
    }
    for(int i=1; i<=ftop; i++) {
        factor[i][1]*=b;
    }
    /*for(int i=1; i<=ftop; i++) {
        printf("%lld %lld
",factor[i][0],factor[i][1]);
    }*/
}

ll da;

ll qpow(ll x,ll n) {
    x%=mod;
    ll res=1;
    while(n) {
        if(n&1) {
            res*=x;
            if(res>=mod)
                res%=mod;
        }
        x*=x;
        if(x>=mod)
            x%=mod;
        n>>=1;
    }
    if(res>=mod)
        res%=mod;
    return res;
}

void calc() {
    ll pro=1;
    for(int i=1; i<=ftop; i++) {
        ll sum=0;
        ll &p=factor[i][0];
        ll &k=factor[i][1];

        if((p-1)%mod==0) {
            //退化为等差数列
            sum=k+1;
        } else {
            sum=(qpow(p,k+1)-1+mod)%mod;
            //printf("sum=%lld
",sum);
            sum*=qpow(p-1,mod-2);
        }
        if(sum>=mod)
            sum%=mod;
        //printf("sum=%lld
",sum);

        pro*=sum;
        if(pro>=mod)
            pro%=mod;
    }

    da=pro%mod;
}

int main() {
#ifdef Yinku
    freopen("Yinku.in","r",stdin);
#endif // Yinku
    scanf("%lld%lld",&a,&b);
    if(a==0) {
        printf("0
");
        return 0;
    }
    fj();
    calc();
    printf("%lld
",da);
}
原文地址:https://www.cnblogs.com/Yinku/p/10989833.html