大致题意:
求A^B的所有约数(即因子)之和,并对其取模 9901再输出。
解题思路:
要求有较强 数学思维 的题
应用定理主要有三个:
要求有较强 数学思维 的题
应用定理主要有三个:
(1) 整数的唯一分解定理:
任意正整数都有且只有一种方式写出其素因子的乘积表达式。
A=(p1^k1)*(p2^k2)*(p3^k3)*....*(pn^kn) 其中pi均为素数
(2) 约数和公式:
对于已经分解的整数A=(p1^k1)*(p2^k2)*(p3^k3)*....*(pn^kn)
有A的所有因子之和为
S = (1+p1+p1^2+p1^3+...p1^k1) * (1+p2+p2^2+p2^3+….p2^k2) * (1+p3+ p3^3+…+ p3^k3) * .... * (1+pn+pn^2+pn^3+...pn^kn)
(3) 同余模公式:
(a+b)%m=(a%m+b%m)%m
(a*b)%m=(a%m*b%m)%m
用等比数列求和公式,但是要用逆元。用如下公式即可
因为可能会很大,超过int范围,所以在快速幂时要二分乘法。
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
typedef long long LL;
const int N = 10005;
const int MOD = 9901;
bool prime[N];
int p[N];
int cnt;
void isprime()
{
cnt = 0;
memset(prime,true,sizeof(prime));
for(int i=2; i<N; i++)
{
if(prime[i])
{
p[cnt++] = i;
for(int j=i+i; j<N; j+=i)
prime[j] = false;
}
}
}
//1
LL inv1(LL t, LL p)
{//求t关于p的逆元,注意:t要小于p,最好传参前先把t%p一下
return t == 1 ? 1 : (p - p / t) * inv1(p % t, p) % p;
}
long long pow_m(long long a,long long n)//快速模幂运算
{
long long res=1;
long long tmp=a%MOD;
while(n)
{
if(n&1){res*=tmp;res%=MOD;}
n>>=1;
tmp*=tmp;
tmp%=MOD;
}
return res;
}
// 2
LL multi(LL a,LL b,LL m)
{
LL ans = 0;
a %= m;
while(b)
{
if(b & 1)
{
ans = (ans + a) % m;
b--;
}
b >>= 1;
a = (a + a) % m;
}
return ans;
}
LL quick_mod(LL a,LL b,LL m)
{
LL ans = 1;
a %= m;
while(b)
{
if(b & 1)
{
ans = multi(ans,a,m);
b--;
}
b >>= 1;
a = multi(a,a,m);
}
return ans;
}
void Solve(LL A,LL B)
{
LL ans = 1;
for(int i=0; p[i]*p[i] <= A; i++)
{
if(A % p[i] == 0)
{
int num = 0;
while(A % p[i] == 0)
{
num++;
A /= p[i];
}
LL M = (p[i] - 1) * MOD;
ans *= (pow_m(p[i],num*B+1) - 1)*inv1(p[i]-1,MOD);
ans %= MOD;
}
}
if(A > 1)
{
LL M = MOD * (A - 1);
ans *= (quick_mod(A,B+1,M) + M - 1) / (A - 1);
ans %= MOD;
}
cout<<ans<<endl;
}
int main()
{
LL A,B;
isprime();
while(cin>>A>>B)
Solve(A,B);
return 0;
}