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

LINK:[2440中山市选2011 完全平方数]
这个中山市太强了 还有市选。。

之所以做这道题是因为这道题 有一个朋友给我的题目 我没想出来 和这道题类似。注意 活用容斥!

楔子:求出1~n内所有不含平方质因数的数字个数。\(n\leq 10^{12}\)

更形象一点\(\sum_{i=1}^{n}\mu(i)^2\) 对这个东西求和。

想了一会杜教筛 发现搞不了 没有什么积性函数能卷这个东西得到一个比较好的积性函数。

min25?我也不会我也不懂。。。

考虑容斥 我们还是利用质因数来筛 首先被筛掉的是 n/p*p 这说明了\(p\leq 10^6\).

发现这样筛下去即可 容斥系数使用\(\mu\)即可。

那现在可以考虑这道题了 第k个数。

求第k大 直接上二分。考虑如何check 直接暴力容斥出mid之内有多少个数字是非完全平方的即可。

总复杂度 Tlogksqrt(k) .

const ll MAXN=1000010;
ll T,n,maxx,top;
ll p[MAXN],v[MAXN],mu[MAXN];
inline void prepare()
{
	mu[1]=1;
	rep(2,maxx,i)
	{
		if(!v[i])
		{
			p[++top]=v[i]=i;
			mu[i]=-1;
		}
		rep(1,top,j)
		{
			if(maxx/i<p[j])break;
			v[i*p[j]]=p[j];
			if(v[i]==p[j])break;
			mu[i*p[j]]=-mu[i];
		}
	}
}
inline ll calc(ll n)
{
	ll ans=0;
	for(ll i=1;i*i<=n;++i)ans+=mu[i]*n/(i*i);
	return ans;
}
int main()
{
	freopen("1.in","r",stdin);
	get(T);maxx=1000010;
	prepare();
	//printf("%lld\n",calc(10000000000ll));
	while(T--)
	{
		get(n);
		ll l=1,r=10000000000ll;
		while(l<r)
		{
			ll mid=(l+r)>>1;
			if(calc(mid)>=n)r=mid;
			else l=mid+1;
		}
		printf("%lld\n",r);
	}
	return 0;
}

二分上界可以自己算一下。

posted @ 2020-03-16 19:05  chdy  阅读(98)  评论(0编辑  收藏  举报