Sumdiv
Description
Consider two natural numbers A and B. Let S be the sum of all natural divisors of A^B. Determine S modulo 9901 (the rest of the division of S by 9901).
Input
The only line contains the two natural numbers A and B, (0 <= A,B <= 50000000)separated by blanks.
Output
The only line of the output will contain S modulo 9901.
Sample Input
2 3
Sample Output
15
Hint
2^3 = 8.
The natural divisors of 8 are: 1,2,4,8. Their sum is 15.
15 modulo 9901 is 15 (that should be output).
The natural divisors of 8 are: 1,2,4,8. Their sum is 15.
15 modulo 9901 is 15 (that should be output).
/**
题意:求A^B的所有约数之和 Mod 9901。
思路:大数模运算。两个最基本公式:(A*B)%C = ((A%C)*(B%C))%C 和 (A+B)%C = ((A%C)+(B%C))%C 。
1: 对A进行素因子分解得
A = p1^a1 * p2^a2 * p3^a3 *...* pn^an.
故 A^B = p1^(a1*B) * p2^(a2*B) *...* pn^(an*B);
2:A^B的所有约数之和为:
sum = [1+p1+p1^2+...+p1^(a1*B)] * [1+p2+p2^2+...+p2^(a2*B)] *...* [1+pn+pn^2+...+pn^(an*B)].
如 200 = 2^3 * 5^2 : sum(200) = [1 + 2 + 4 + 8] * [1 + 5 + 25].
3: 求等比数列1+pi+pi^2+pi^3+...+pi^n可以由递归形式的二分求得:(模运算不能用等比数列和公式!)
若n为奇数,一共有偶数项,则:
1 + p + p^2 + p^3 +...+ p^n
= (1+p^(n/2+1)) + p * (1+p^(n/2+1)) +...+ p^(n/2) * (1+p^(n/2+1))
= (1 + p + p^2 +...+ p^(n/2)) * (1 + p^(n/2+1))
如:1 + p + p^2 + p^3 + p^4 + p^5 = (1 + p + p^2) * (1 + p^3)
若n为偶数,一共有奇数项,则:
1 + p + p^2 + p^3 +...+ p^n
= (1+p^(n/2+1)) + p * (1+p^(n/2+1)) +...+ p^(n/2-1) * (1+p^(n/2+1)) + p^(n/2)
= (1 + p + p^2 +...+ p^(n/2-1)) * (1+p^(n/2+1)) + p^(n/2);
如:1 + p + p^2 + p^3 + p^4 = (1 + p) * (1 + p^3) + p^2
**/
#include <map>
#include <set>
#include <list>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <vector>
#include <bitset>
#include <cstdio>
#include <string>
#include <numeric>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};//up down left right
bool inmap(int x,int y,int n,int m){if(x<1||x>n||y<1||y>m)return false;return true;}
int hashmap(int x,int y,int m){return (x-1)*m+y;}
#define eps 1e-8
#define inf 0x7fffffff
#define debug puts("BUG")
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define read freopen("in.txt","r",stdin)
#define write freopen("out.txt","w",stdout)
#define Max 50000001
#define maxn 8008
#define mod 9901
int p[maxn];//Primer
int cnt[maxn];
int N,K;
ll Pow(ll n,ll k)//自写快速幂
{
ll ans=1;
while(k>0)//要记住
{
if(k&1)
ans=(ans*n)%mod;
k>>=1;
n=n*n%mod;
}
return ans;
}
ll sum(ll n,ll k)//递归求和
{
if(k==0)
return 1;
if(k&1)
return ((1+Pow(n,k/2+1))*sum(n,k/2))%mod;
else
return ((1+Pow(n,k/2+1))*sum(n,k/2-1)+Pow(n,k/2))%mod;
}
int main()
{
while(~scanf("%d%d",&N,&K))
{
int k=0;
for(int i=2;i*i<=N;i++)
{
if(N%i==0)
{
p[k]=i;//显然,i一定是素数
while(N%i==0)
{
N/=i;
cnt[k]++;
}//算出了基本算数定理中每一个素数的幂,N是不断变化的,使得i能够一直是素数
}
k++;
}
if(N!=1)//N有可能是素数,那前面的循环中的if就会一次也没有执行
{
p[k]=N;
cnt[k++]=1;
}
ll ans=1;
for(int i=0;i<k;i++)
ans=ans*(sum(p[i],cnt[i]*K)%mod)%mod;
printf("%lld\n",ans);
}
return 0;
}