洛谷 - P1593 - 因子和 - 费马小定理
类似的因为模数比较小的坑还有卢卡斯定理那道,也是有时候逆元会不存在,因为整除了。使用一些其他方法避免通过逆元。
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\n",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\n",sum);
sum*=qpow(p-1,mod-2);
}
if(sum>=mod)
sum%=mod;
//printf("sum=%lld\n",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\n");
return 0;
}
fj();
calc();
printf("%lld\n",da);
}