看ACdreamers大神博客学习数论知识。
大家都能想到的东西:
g(n)=∑d|nnd∗ϕ(nd)=∑d|nd∗ϕ(d)
n=pα11∗pα22∗...∗pαkk
此时有一个定理 g(n)=(p2α1+11+1p1+1)∗(p2α2+12+1p2+1)∗...∗(p2αk+1k+1pk+1)
所以 f(n)g(n)=(p1+1)∗(p2+1)∗...∗(pk+1)
下面来写证明过程:
因为 phi(n) 是积性函数, h(n)=n 也是积性函数,所以 g(n)=∑d|nh(d)∗ϕ(d) 也是积性函数。
所以 g(n)=g(pα11)∗g(pα22)∗...∗g(pαkk) 。
只需证明 g(pα11)=p2α1+11+1p1+1 即可。
显然我们能够得到: ϕ(pn1)=pn1−pn−11
g(pα11)=∑d|pα11d∗ϕ(d)=1+∑i=1α1pi1∗(pi1−pi−11)=p2α1+11+1p1+1
证毕。
这题卡了一个 o(n−−√) 的质因数分解,预处理出 [1,106]内所有质数 ,直接用质数来分解就可以了。说到底,这道题只要知道那个定理了,就是水题了。
#include <bits/stdc++.h>
#define LL long long
#define FOR(i,x,y) for(int i = x;i < y;++ i)
#define IFOR(i,x,y) for(int i = x;i > y;-- i)
using namespace std;
const int Mod = 1000000007;
const int maxn = 1000100;
int prime[maxn];
bool check[maxn];
LL n;
void Get_Prime(){
memset(check,false,sizeof(check));
prime[0] = 0;
FOR(i,2,maxn){
if(!check[i]){
prime[++prime[0]] = i;
}
FOR(j,1,prime[0]+1){
if(i*prime[j] >= maxn) break;
check[i*prime[j]] = true;
if(i%prime[j] == 0) break;
}
}
}
void work(){
scanf("%I64d",&n);
LL res = 1;
for(int i = 1;i <= prime[0];++ i){
if((LL)prime[i]*prime[i] > n) break;
if(n%prime[i] == 0){
res = (res*(prime[i]+1))%Mod;
}
while(n%prime[i] == 0){
n /= prime[i];
}
}
if(n > 1){
n++;
n %= Mod;
res = (res*n)%Mod;
}
printf("%I64d\n",res);
}
int main()
{
//freopen("test.in","r",stdin);
Get_Prime();
int T; scanf("%d",&T);
while(T--){
work();
}
return 0;
}