根据算术基本定理,(其中pi 为素数,且p1<p2<p3..)
猜想:f(a*b)=f(a)*f(b) ,a,b 互质
不妨假设 , ( a是最小的素因子)
if n 为质数 ,那么f(n)=2
else if 存在 x >=3,那么f(n)=0, 因为n分成两份,有三个相同pi,必有两个pi分到同一组
else if 存在 x <=2 && x !=1,那么f(n)=f(n/ a*a), 这两个相同的pi 必须分到两个组,那么同时舍去这两个对结果并无影响
else if x=1, f(n)=2*f( n / a) ,因为当x=1 时,f(n/a) 的所有情况都可以加入a,且对于每一种情况,a都可以加入到左边或右边,
所以有2*f(n/a)种情况
所以只需找到n的最小素因子a,然后看a有几次幂就可以
线性筛就可以
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=2e7+4;
int pri[maxn];
int u[maxn];
long long f[maxn]={0,1,2,2};
void is_prime(){
int cnt=0;
for(int i=2;i<=maxn;i++){
if(!u[i])
pri[++cnt]=i,f[i]=2;
for(int j=1;j<=cnt;j++){
int num=i*pri[j];
if(num>maxn)
break;
u[num]=1;
if(i%(pri[j]*pri[j])==0){
f[num]=0;
break;
}
else if(i%pri[j]==0){
f[num]=f[i/pri[j]];
break;
}
else
f[num]=2*f[i];
}
}
}
int main(){
int n;
scanf("%d",&n);
is_prime();
for(int i=1;i<=maxn;i++){
f[i]+=f[i-1];
}
int a;
for(int i=1;i<=n;i++){
scanf("%d",&a);
printf("%lld\n",f[a]);
}
return 0;
}