POJ 1845乘法逆元+约数和
乘法逆元计算等比数列的求和公式
题意
给两个正整数A和B,计算AB的所有因子和的值对9901取模
思路
约数和公式
S=(1+p1+p1^2+.....+p1^k1)*(1+p2+p2^2+.....+p2^k2)*......*(1+pn+pn^2+pn^3+.....+pn^kn);
等比数列公式:(PB+c+1-1) / (p1-1)
当模数mod为质数时,bmod-2逆元即为b的乘法逆元
当p-1不为mod的倍数时,逆元无效,此时p%mod = = 1,所以分母即为1 + 12 + .....+1B+c
#include <iostream> #include <cstdio> using namespace std; typedef long long ll; const int maxn = 2e5+10; int m; int p[100],c[100]; void divide(ll n) { m = 0; for(int i = 2;i*i <= n;++i){ if(n % i == 0){ p[++m] = i; while(n%i==0){ n/=i; c[m]++; } } } if(n > 1){ p[++m] = n; c[m] = 1; } } ll multi(ll a,ll b,ll mod) { ll ret=0; while(b) { if(b&1) ret=(ret+a)%mod; a=(a<<1)%mod; b=b>>1; } return ret; } ll powmod(ll a,ll b,ll mod) { ll ret=1; while(b) { if(b&1) ret=multi(ret,a,mod); //直接相乘的话可能会溢出 a=multi(a,a,mod); b=b>>1; } return ret; } int main() { // freopen("input.txt", "r", stdin); ll a,b; scanf("%lld%lld",&a,&b); divide(a); // cout<<m<<endl; int mod = 9901; ll ans = 1; for(int i = 1;i <= m;++i){ ll nub = c[i]*b; if((p[i]-1)%mod == 0){ ans = ((nub+1)%mod * ans%mod)%mod; continue; } ll x = (powmod(p[i],nub+1,mod) - 1 + mod)%mod; ll y = powmod(p[i]-1,mod-2,mod); ans = ((x*y)%mod * ans)%mod; } printf("%lld\n",ans ); }