地址:https://nanti.jisuanke.com/t/30999
果然是菜。。。。n = p1^a1*p2^a2*p3^a3………..,如果a1,a2,a3….有一个数大于2,则f(n) = 0;假设有m个ai = 1,则f(n) = 2 ^ m;如果有0个,f(n) = 1;
不能一个一个的分解质因数求解,得先打表预处理,用素数筛来打f表
当p 为素数时,f(p) = 2;
当i % p == 0时,如果i % p^2 == 0,f(i * p) = 0;否则f(i * p) = f(i) / 2;
当i % p != 0时,f(i * p) = f(i) * 2;
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int inf = 0x3f3f3f3f;
const int MAXN=20000010;
int prime[MAXN];
short ans[MAXN];
void getprime()
{
memset(prime,0,sizeof(prime));
//prime[0]储存<=MAXN的素数个数
int i,j;
for(i=2;i<MAXN;++i)
{
if(!prime[i]){ prime[++prime[0]]=i;ans[i] = 2;}//判断是素数,就储存到对应的第几个数组中中
for(j=1;j<=prime[0]&&prime[j]*i<=MAXN;++j)
{
prime[prime[j]*i]=1;
if(i % prime[j] == 0){
if(i % (prime[j] * prime[j]) == 0){
ans[i * prime[j]] = 0;
}
else{
ans[i * prime[j]] = ans[i] / 2;
}
}else{
ans[i * prime[j]] = ans[i] * 2;
}
if(i%prime[j]==0) break;
//如果i和prime[j]中的素数相同,就跳出,防止发生重复
//使上式永远都是小素数乘以大素数
}
}
}
int main()
{
memset(ans,0,sizeof(ans));
ans[1] = 1;
getprime();
// for(int i = 1;i <= 100;++i)
// {
// cout << i << " " << ans[i] << endl;
// }
//cout << prime[0] << endl;
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
LL sum = 0;
for(int i = 1;i <= n;++i)
{
sum += (LL)ans[i];
}
printf("%lld\n",sum);
}
return 0;
}