[中山市选2011][bzoj2440] 完全平方数 [二分+莫比乌斯容斥]

题面

传送门

思路

新姿势get

莫比乌斯容斥

$\sum_{i=1}{n}\mu(i)f(i)$

这个东西可以把所有没有平方质因子的东西表示出来,还能容斥掉重复的项

证明是根据莫比乌斯函数的定义,显然

于是本题里面,我们二分答案$K$,那么闭区间$[1,K]$中的没有平方质因子的数的个数就是$\sum_{i=1}{\sqrt{K}}\mu(i)\frac{K}{i2}$

然后线性筛一波,单次询问复杂度$O(log_2maxn\sqrt{K})$,$maxn$是二分上界

Code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cassert>
#include<cmath>
#define ll long long
using namespace std;
inline int read(){
	int re=0,flag=1;char ch=getchar();
	while(ch>'9'||ch<'0'){
		if(ch=='-') flag=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
	return re*flag;
}
ll mu[100010],pri[100010],cntp,vis[100010];
void init(){
	ll i,j,k,len=100000;mu[1]=1;
	for(i=2;i<=len;i++){
		if(!vis[i]) pri[++cntp]=i,mu[i]=-1;
		for(j=1;j<=cntp;j++){
			k=i*pri[j];if(k>len) break;
			vis[k]=1;
			if(i%pri[j]==0){mu[k]=0;break;}
			mu[k]=-mu[i];
		}
	}
} 
ll cntsqr(ll lim){
	ll i,len=sqrt(lim);ll re=0;
	for(i=1;i<=len;i++) re+=mu[i]*(lim/(i*i));
	return re;
}
int main(){
	int T=read();ll n,l,r,mid;
	init();
	while(T--){
		n=read();
		l=1;r=10000000000;
		while(l<r){
			mid=(l+r)>>1;
			if(cntsqr(mid)>=n) r=mid;
			else l=mid+1;
		}
		printf("%lld\n",l);
	}
}
posted @ 2018-08-07 15:18  dedicatus545  阅读(182)  评论(0编辑  收藏  举报