Time:2016.05.29
Author:xiaoyimi
转载注明出处谢谢
传送门
思路:
这是一个和μ函数有很大关系的题目
x以内的无平方因子数=无需是任何质数的倍数的数的数量(即x)-是至少一个质数平方倍数的数的数量+是至少两个质数平方倍数的数的数量-是至少三个质数平方倍数的数的数量…
看一下μ函数的定义
具体操作就是在[0,2n](据说可以证明上界是2n???)每次二分判断x以内的非平方倍数是否大于等于n,是就令r=mid-1,反之就是l=mid+1,判断时就是
∑n√i=1⌊μ(i)∗ni2⌋
注意:
l,r,mid计算时要开long long(或者unsigned int)
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#define LL long long
using namespace std;
int T,n;
int prime[50000],mu[50000];
int vis[50000];
int in()
{
char ch=getchar();int t=0;
while (!isdigit(ch)) ch=getchar();
while (isdigit(ch)) t=(t<<1)+(t<<3)+ch-48,ch=getchar();
return t;
}
void init()
{
mu[1]=1;
for (int i=2;i<=46500;i++)
{
if (!vis[i])
prime[++prime[0]]=i,
mu[i]=-1;
for (int j=1;j<=prime[0];j++)
if (i*prime[j]>46500) break;
else
{
vis[i*prime[j]]=1;
if (i%prime[j])
mu[i*prime[j]]=-mu[i];
else{mu[i*prime[j]]=0;break;}
}
}
}
bool judge(int x,int k)
{
int ans=0;
for (int i=1;i<=sqrt(x);i++)
ans+=mu[i]*x/(i*i);
return ans<k;
}
int solve(int k)
{
int l=0,r=k<<1,ans=0;
for (int mid=l+r>>1;l<=r;mid=(LL)l+r>>1)
if (judge(mid,k)) l=mid+1;
else ans=mid,r=mid-1;
return ans;
}
main()
{
init();
T=in();
while(T--)
n=in(),
printf("%d\n",solve(n));
}