题意:全然平方数是指含有平方数因子的数。求第ki个非全然平方数。
解法:比較明显的二分,getsum(int middle)求1-middle有多少个非全然平方数,然后二分。求1-middle的非全然平方数个数能够用总数减掉全然平方数个数。计算全然平方数的个数用容斥:
首先加上n/(2*2)+n/(3*3)+n/(5*5)+n/(7*7)...+...然后减掉出现两次的,然后加上三次的...奇加偶减。这就是mou的原型,用mou数组计算非常easy;
代码:
/******************************************************
* @author:xiefubao
*******************************************************/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <string.h>
//freopen ("in.txt" , "r" , stdin);
using namespace std;
#define eps 1e-8
#define zero(_) (abs(_)<=eps)
const double pi=acos(-1.0);
typedef unsigned long long LL;
const int Max=100010;
const LL INF=2e16+7;
LL mou[Max];
void init()
{
for(LL i=2; i<Max; i++)
{
if(!mou[i])
{
mou[i]=i;
for(LL j=i*i; j<Max; j+=i)
mou[j]=i;
}
}
mou[1]=1;
for(int i=2; i<Max; i++)
{
if(i/mou[i]%mou[i]==0) mou[i]=0;
else mou[i]=-mou[i/mou[i]];
}
}
int k;
LL getnum(LL middle)
{
LL ans=0;
for(LL i=1; i*i<=middle; i++)
{
ans+=mou[i]*(middle/(i*i));
}
return ans;
}
int main()
{
init();
int t;
cin>>t;
while(t--)
{
scanf("%d",&k);
LL left=1,right=INF;
while(left<=right)
{
int middle=(left+right)/2;
if(getnum(middle)<k)
left=middle+1;
else
right=middle-1;
}
cout<<left<<'\n';
}
return 0;
}