https://nanti.jisuanke.com/t/30999
f[i]表示将i分解为2个数相乘的方案数,i = a*b,且a,b均不能有平方因子。
求f[i]前缀和
n = p1^a1 * p2^a2 * p3^a3 * ... * pk^ak
= a * b
若a1 = 1,则a可能有p1,可能没有,f[n] = f[n / p1] * 2
a1 = 2,则a必须选p1(a,b一人一个),f[n] = f[n / (p1 * p1)]
a1 > 2,无论怎么分一边都有平方因子,f[n] = 0
筛法
1.p为质数,f[p] = 2
2.开始筛i * prime[j]
若i % prime[j] != 0,则i * prime[j]中只有一个prime[j],(a1 = 1),f[i * prime[j]] = f[i] * 2
若i % (prime[j] * prime[j]) == 0,则i * prime[j]中prime[j]对应指数a1 > 2,f[i * prime[j]] = 0
否则,若i % prime[j] == 0,则i * prime[j]中恰好有2个prime[j],a1 = 2,f[i * prime[j]] = f[i]
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 2e7 + 1;
bool noprime[maxn];
int prime[maxn / 10],sz = 0;
long long f[maxn];
void solve()
{
f[1] = 1;
for (int i = 2; i < maxn; i ++) {
if(!noprime[i]) {prime[sz ++] = i;f[i] = 2; }
for (int j = 0; j < sz && i * prime[j] < maxn; j ++) {
noprime[i * prime[j]] = true;
if(i % (1ll * prime[j] * prime[j]) == 0){
long long t = 1ll * i * prime[j] * prime[j];
if(t < maxn) f[t] = 0;
}
else if(i % prime[j] == 0){
f[1ll * i * prime[j]] = f[i / prime[j]];
break;
}
else{
f[i * prime[j]] = f[i] * 2;
}
}
}
for (int i = 2; i < maxn; i ++) {
f[i] += f[i - 1];
}
}
int main()
{
solve();
int T;scanf("%d",&T);
int n;
while (T --) {
scanf("%d",&n);
printf("%lld\n",f[n]);
}
return 0;
}