洛谷 P4318 徹底平方數

題目描述

小 X 自幼就很喜歡數。但奇怪的是,他十分討厭徹底平方數。他以爲這些數看起來很使人難受。由此,他也討厭全部是徹底平方數的正整數倍的數。然而這絲絕不影響他對其餘數的熱愛。c++

這天是小X的生日,小 W 想送一個數給他做爲生日禮物。固然他不能送一個小X討厭的數。他列出了全部小X不討厭的數,而後選取了第 K個數送給了小X。小X很開心地收下了。測試

然而如今小 W 卻記不起送給小X的是哪一個數了。你能幫他一下嗎?spa

輸入輸出格式

輸入格式:

包含多組測試數據。文件第一行有一個整數 T,表示測試數據的組數。 第2 至第T+1 行每行有一個整數Ki,描述一組數據,含義如題目中所描述。code

輸出格式:

含T 行,分別對每組數據做出回答。第 i 行輸出相應的第Ki 個不是徹底平方數的正整數倍的數。blog

輸入輸出樣例

輸入樣例#1: 
4 
1 
13 
100 
1234567
輸出樣例#1: 
1 
19 
163 
2030745

說明

對於 50%的數據有 1 ≤ Ki ≤ 10^5, 對於 100%的數據有 1 ≤ Ki ≤ 10^9, T ≤ 50it

 

二分答案以後反演一下能夠 O(sqrt(N)) 計算 μ^2 的前綴和。io

 

#include<bits/stdc++.h>
#define maxn 300000
#define ll long long
using namespace std;
int zs[maxn/2],t=0,miu[maxn+5];
bool v[maxn+5];

inline void init(){
	miu[1]=1;
	for(int i=2;i<=maxn;i++){
		if(!v[i]) zs[++t]=i,miu[i]=-1;
		for(int j=1,u;j<=t&&(u=zs[j]*i)<=maxn;j++){
			v[u]=1;
			if(!(i%zs[j])) break;
			miu[u]=-miu[i];
		}
	}
}

inline ll calc(ll x){
	ll an=0;
	for(int i=1;i*(ll)i<=x;i++) an+=miu[i]*(x/(i*(ll)i));
	return an;
}

int main(){
	init();
	int T,n; ll l,r,mid,ans;
	scanf("%d",&T);
	while(T--){
		scanf("%d",&n);
		l=1,r=1e11;
		while(l<=r){
			mid=l+r>>1;
			if(calc(mid)>=n) ans=mid,r=mid-1;
			else l=mid+1;
		}
		printf("%lld\n",ans);
	}
	
	return 0;
}
相關文章
相關標籤/搜索