[bzoj2440] [中山市选2011]完全平方数

Description

小 X 自幼就很喜欢数。但奇怪的是,他十分讨厌完全平方数。他觉得这些数看起来很令人难受。由此,他也讨厌所有是完全平方数的正整数倍的数。然而这丝毫不影响他对其他数的热爱。
这天是小X的生日,小 W 想送一个数给他作为生日礼物。当然他不能送一个小X讨厌的数。他列出了所有小X不讨厌的数,然后选取了第 K个数送给了小X。小X很开心地收下了。
然而现在小 W 却记不起送给小X的是哪个数了。你能帮他一下吗?

Input

包含多组测试数据。文件第一行有一个整数 T,表示测试数据的组数。
第2 至第T+1 行每行有一个整数Ki,描述一组数据,含义如题目中所描述。

Output

含T 行,分别对每组数据作出回答。第 i 行输出相应的
第Ki 个不是完全平方数的正整数倍的数。

Sample Input

4 
1 
13 
100 
1234567

Sample Output

1 
19 
163 
2030745 

Solution

显然满足单调性,可以二分。

然后问题转化为了\(1\)\(n\)内有多少个满足条件的数。

对于一个满足条件的数,即每个质因子的指数都是1。

对于一个数\(x=\prod_{i=1}^kp_i^{a_i}\cdot s\),其中前面的\(\prod\)表示\(\forall i,a_i\geqslant 2\)的部分,后面是剩下的。

考虑当且仅当\(k=0\)时,这个数才会被计一次,\(k\ne 0\)时,一次都不会记。

可以想到这样一个函数:

\[\sum_{d|n}\mu(d)=[n=1] \]

于是可以枚举每个完全平方数\(x^2\),剩下的质因子随便填,然后乘上\(\mu(x)\),这样正好可以满足每个满足条件的数被记一次。

#include<bits/stdc++.h>
using namespace std;

#define int long long 

#define ONLINE_JUDGE

#ifdef ONLINE_JUDGE
#define getchar() ((p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin)),p1==p2)?EOF:*p1++)
#endif

namespace fast_IO {
	char buf[1<<21],*p1=buf,*p2=buf;

	template <typename T> inline void read(T &x) {
		x=0;T f=1;char ch=getchar();
		for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
		for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
	}
	template <typename T,typename... Args> inline void read(T& x,Args& ...args) {
		read(x),read(args...);
	}

	char buf2[1<<21],a[80];int p,p3=-1;

	inline void flush() {fwrite(buf2,1,p3+1,stdout),p3=-1;}
	template <typename T> inline void write(T x) {
		if(p3>(1<<20)) flush();
		if(x<0) buf2[++p3]='-',x=-x;
		do {a[++p]=x%10+48;} while(x/=10);
		do {buf2[++p3]=a[p];} while(--p);
		buf2[++p3]='\n';
	}
	template <typename T,typename... Args> inline void write(T x,Args ...args) {
		write(x),write(args...);
	}
}

using fast_IO :: read;
using fast_IO :: write;
using fast_IO :: flush;

const int maxn = 1e6+10;

int pri[maxn],tot,vis[maxn],mu[maxn];

void sieve() {
	mu[1]=1;
	for(int i=2;i<maxn;i++) {
		if(!vis[i]) pri[++tot]=i,mu[i]=-1;
		for(int j=1;j<=tot&&i*pri[j]<maxn;j++) {
			vis[i*pri[j]]=1;
			if(i%pri[j]==0) break;
			mu[i*pri[j]]=-mu[i];
		}
	}
}

int check(int n) {
	int tmp=0;
	for(int i=1;i*i<=n;i++) tmp=tmp+mu[i]*n/(i*i);
	return tmp;
}

void solve() {
	int n,l,r,mid,ans=1;read(n);l=1,r=n*2;
	while(l<=r) {
		mid=((l+r)>>1);
		if(check(mid)>=n) ans=mid,r=mid-1;
		else l=mid+1;
	}write(ans);
}

signed main() {
	sieve();
	int t;read(t);while(t--) solve();
	flush();
	return 0;
}
posted @ 2019-01-02 15:00  Hyscere  阅读(72)  评论(0编辑  收藏  举报