题意
定义一个数x合法为x无法表示成a^k(k!=1)。
给出T个询问,求小于n内不合法的数的个数。
特性
不合法的数一定是一个数的几次方,即如果所有的a^k的数。
题解
构造+二分
不妨构造出所有的a^k的数,但是这些数整容太庞大了。
我们考虑去掉所有a^2的数,这样规模就控制在了可行范围内。
最后的时候减掉n之内a^2的数就可以了,这些数有sqrt(n)个。
提醒一句,注意精度的问题。
代码
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN=3000000;
const ll LIM=1e18;
ll f[1003500];int tot=0;
inline bool check(ll x)
{
ll t=sqrt(x);
return t*t<x;
}
int main()
{
for(ll i=2;i<=1000000;i++)
for(ll x=i*i;x<=LIM/i;)
{
x*=i;
if(check(x)) f[++tot]=x;
}
sort(f+1,f+tot+1);
tot=unique(f+1,f+tot+1)-(f+1);
int T;scanf("%d",&T);
while(T--)
{
ll x;scanf("%lld",&x);
ll ans=x-(upper_bound(f+1,f+tot+1,x)-f-1)-(ll)sqrt(x);//debug sqrt(x)需要ll由double转为 ll
printf("%lld\n",ans);
}
return 0;
}