POJ1845:http://poj.org/problem?id=1845
思路:
AB可以表示成多个质数的幂相乘的形式:AB=(a1n1)*(a2n2)* ...*(amnm)
根据算数基本定理可以得约数之和sum=(1+a1+a12+...+a1n1)*(1+a2+a22+...+a2n2)*...*(1+am+am2+...+amnm) mod 9901
对于每个(1+ai+ai2+...+aini) mod 9901=(ai(ni+1)-1)/(ai-1) mod 9901 (等比数列前n项目和)分母可用快速幂算出
因为9901是质数,只要ai-1不是9901的倍数就只要计算ai-1的乘法逆元inv(用费马小定理),再乘(ai(ni+1)-1) 直接算出ans
PS:若ai-1是9901的倍数 此时乘法逆元不存在 但是ai mod 9901=1 所以1+ai+ai2+...+aini=1+1+...+1=ni+1
代码:
#include<iostream>
#include<cmath>
#include<cstdio>
using namespace std;
#define mod 9901
int a,b,m,ans=
1;
int p[
20],c[
20];
//p是质数 c是指数
void divide(
int n)
{
m=
0;
for(
int i=
2;i*i<=n;i++
)
{
if(n%i==
0)
{
p[++m]=
i;
c[m]=
0;
while(n%i==
0)
{
n/=
i;
c[m]++
;
}
}
}
if(n>
1)
{
p[++m]=
n;
c[m]=
1;
}
}
int quickpow(
int a,
long long b)
{
int c=
1;
for(;b;b>>=
1)
{
if(b&
1)
c=(
long long)c*a%
mod;
a=(
long long)a*a%
mod;
}
return c;
}
int main()
{
cin>>a>>
b;
divide(a);//分解A的质因数 b到后面在乘上
for(
int i=
1;i<=m;i++
)
{
if((p[i]-
1)%mod==
0)
//特判当ai-1是9901的倍数 乘法逆元不存在
{
ans=((
long long)b*c[i]+
1)%mod*ans%
mod;
continue;
}
int x=quickpow(p[i],(
long long)b*c[i]+
1);
//快速幂求分母
x=(x-
1+mod)%
mod;
int y=p[i]-
1;
y=quickpow(y,mod-
2);
//根据费马小定理求乘法逆元
ans=(
long long)ans*x%mod*y%
mod;
}
cout<<
ans;
}
View Code
转载于:https://www.cnblogs.com/BrokenString/p/9655109.html