作为 min-25 筛的模板题,本题可以使用 min-25 筛 / 洲阁筛 等亚线性积性函数求和的方法在
算法一
这种解法的思路参考自 zzq's blog .
定义:Powerful Number
若正整数
性质
证明:
由于每个质因子间是独立的,显然所有 Powerful Number 都可以表示成
a^2b^3 的形式。考虑枚举a ,则n 以内这种数的数量为
O\left(\sum_{a=1}^{\sqrt n}\left(\frac n{a^2}\right)^{\frac 1 3}\right)
=O\left(\int_1^{\sqrt n}\left(\frac n{x^2}\right)^{\frac 1 3}dx\right)
=O(\sqrt n)
这个性质保证了该算法的复杂度。
本题思路
设
因为
考虑答案。答案为
根据欧拉函数的有关性质,
归纳可证
搜索
这个做法的时间复杂度是
代码
#include <cstdio>
#include <cmath>
#include <cstring>
typedef long long ll;
const int MAXN=5500000;
const int MOD=1E9+7;
const int INV2=500000004, INV6=166666668;
ll n; int lim, cp, ans;
int pri[MAXN], phi[MAXN];
bool flag[MAXN];
int g1[MAXN], g2[MAXN];
void prework()
{
memset(flag, 0, sizeof flag);
phi[1]=1;
for (int i=2; i<=lim; i++)
{
if (!flag[i]) pri[++cp]=i, phi[i]=i-1;
for (int j=1; j<=cp&&i*pri[j]<=lim; j++)
{
flag[i*pri[j]]=1;
if (i%pri[j]==0)
{
phi[i*pri[j]]=phi[i]*pri[j];
break;
}
phi[i*pri[j]]=phi[i]*(pri[j]-1);
}
}
for (int i=1; i<=lim; i++) g1[i]=(g1[i-1]+1ll*i*phi[i])%MOD;
}
int djs(ll m)
{
if (m<=lim) return g1[m];
if (g2[n/m]) return g2[n/m];
int res=(m%MOD)*((m+1)%MOD)%MOD*((2*m+1)%MOD)%MOD*INV6%MOD;
for (ll i=2, j; i<=m; i=j+1)
{
j=m/(m/i);
res=(res-((i+j)%MOD)*((j-i+1)%MOD)%MOD*INV2%MOD*djs(m/i)%MOD+MOD)%MOD;
}
return g2[n/m]=res;
}
void dfs(int k, ll m, int h)
{
if (k>cp||m*pri[k]>n)
{
if (n/m<=lim) ans=(ans+1ll*h*g1[n/m])%MOD;
else ans=(ans+1ll*h*g2[n/(n/m)])%MOD;
return;
}
ll p=1ll*pri[k]*pri[k];
dfs(k+1, m, h);
for (int e=2; m*p<=n; p*=pri[k], e++)
dfs(k+1, m*p, p%MOD*(pri[k]-1)%MOD*(e-1)%MOD*h%MOD);
}
int main()
{
// freopen("P5325.in", "r", stdin);
// freopen("P5325.out", "w", stdout);
scanf("%lld", &n);
lim=pow(n, 2.0/3);
prework(); djs(n);
dfs(1, 1, 1);
printf("%d\n", ans);
return 0;
}