任意数n可以写成 n = p1^k1 * p2^k2 * p3^n3 * ....* pn^kn(p1,p2,...pn为质因数)
n^m 的约数 一定是 p1^m1 * p2 ^m2 *p3^m3 *....* *pn^mn (m1<k1*m,m2<k2*m,....mn<kn*m)
所以约数的和为(p1^0+p1^1+.....+p1^(m*k1))*(p2^0+p2^1+...+p2^(m*k2))*......*(pn^0+pn^1+...+pn^(m*kn))
该多项式展后每一项都为一个约数。
对n^m%mod 可以转换为(n^2)^(m/2)%mod * n^(m%2) %mod = (n^2%mod)^m/2%mod * n^(m%2)%mod
对于前n项和求模,可转为前n/2项 * (1+p^n/2),及可通过递归求解
#include <iostream>
#include <cmath>
#include <cstdio>
using namespace std;
const int mod = 1000000007;
int prime[70000];
int trueprime[70000];
int count = 0;
long long ans=1;
long long yu = 1;
long long powMod(long long m,long long n)
{
yu = 1;
while(n)
{
if(n%2==1)
yu = (yu*m)%mod;
m = m*m%mod;
n/=2;
}
return yu;
}
long long sumMod(long long m,long long n)
{
if(n==0)
return 1;
else if(n==1)
{
return (m+1)%mod;
}
else if(n%2==0)
{
return (((powMod(m,n/2)+1)*sumMod(m,n/2-1))%mod + powMod(m,n)%mod)%mod;
}
else
{
return ((powMod(m,n/2+1)+1)*sumMod(m,n/2))%mod;
}
}
void make_prime()
{
for(int i = 2;i<70000;i++)
{
if(prime[i]==0)
{
if(i < sqrt(70000.0))
{
for(int j = i*i;j<70000;j+=i)
{
prime[j] = 1;
}
}
trueprime[count++] = i;
}
}
}
void getmi(long long m,long long n)
{
for(int i = 0;i<count&&prime[i]*prime[i]<=m;i++)
{
long long mi = 0;
while(m%trueprime[i]==0)
{
mi++;
m /= trueprime[i];
}
mi*=n;
if(mi!=0)
ans = ans*sumMod(trueprime[i],mi)%mod;
}
if(m>1)
ans = ans*sumMod(m,n)%mod;
}
int main()
{
int m;
make_prime();
long long p,q;
scanf("%d",&m);
for(int i = 1;i<=m;i++)
{
ans = 1;
scanf("%lld %lld",&p,&q);
getmi(p,q);
printf("Case %d: %lld\n",i,ans);
}
return 0;
}