题意:
每个数字都是由质因数乘积组成:
于是这个数的所有因子之和就是:
求小于等于n的数中所有质因子之和是偶数的数的个数。
思路:
如上式,求所有质因子之和就是每个质因子(p^0+p^1+p^2+……+p^e)的乘积,所以需要每一项的和都是奇数才能使最终结果为奇数。
当p==2时必为奇数,当p是大于2的质数时只有e为偶数时结果才为奇数,所以直接dfs出所有的特例,然后二分去除特例个数就行了。
特例一共就17w个左右。
代码:
#define N 1123456
#define M 1823456
long long n,m;
long long flag,sum,ave,ans,res,len,ans1,ans2;
long long a[M];
bool mark[N];
long long pri[N],cnt;
void SP()
{
cnt=0;
memset(mark,true,sizeof(mark));
mark[0]=mark[1]=false;
for(long long i=2;i<N;i++)
{
if(mark[i])
pri[cnt++]=i;
for (long long j=0;(j<cnt)&&(i*pri[j]<N);j++)
{
mark[i*pri[j]]=false;
if (i%pri[j]==0)
break;
}
}
}
void dfs(long long step, long long now)
{
a[sum++]=now;
for(long long i=step;i<cnt;i++)
{
long long t = pri[i]*pri[i];
if(i>0&&now>n/t||i==0&&now>n/2)return;
if(i==0)dfs(i,now*2);
else dfs(i,now*pri[i]*pri[i]);
}
}
void init()
{
sum=0;n=1e12;
dfs(0,1);
sort(a,a+sum);
a[sum++]=n+1;
}
int main()
{
long long i,j,k,kk,t,x,y,z
SP();
init();
scanf("%lld",&k);
kk=0;
while(k--)
{
printf("Case %lld: ",++kk);
scanf("%lld",&n);
int len = upper_bound(a,a+sum,n)-a;
printf("%lld\n",n-len);
}
return 0;
}