BZOJ-2440 完全平方数

本文介绍了解决BZOJ-2440完全平方数问题的方法,通过莫比乌斯函数和容斥原理,实现了一个高效的算法。文中详细解释了如何筛选出所有因数指数均为1的数字,并给出了具体的实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

BZOJ-2440 完全平方数

大概题意

求出第k个所有因数指数为1的数字

比如 6=2*3 这就是一个因数指数都为1的数字
反之 9=3*3 3的指数为2 因此不满足要求

首先来看一看莫比乌斯函数

N=p11p12p13...p1k==>μ(N)=(1)k
反之 若有任何一个 pi 的指数 >1 μ(N)=0

这样感觉就解决了我们的问题 所有的数字我们只统计 μ(N)!=0 的即可

但是这道题目的 k 过于大了
所以我们考虑反向求解

正确解法

对于一个数字 N
在枚举 <=N 无完全平方数因子只有一个质因数 的因子 i
根据它的指数为1的质因子的个数,求出 为它平方的数字的个数 Nii

如此一来 我们就把所有的完全平方数的倍数给删去了

但是!!我们好像多删了一些数字…

比如 3*3*16 和 4*4*9 我们分别讨论的是 3 和 4 的平方的倍数
但是不可避免地多删去了一次他们平方的公倍数

于是 我们用容斥定理来解决这个矛盾

每一次 我们删去 含且仅含奇数个质因数因子且无完全平方数因子 的因子的倍数
再加上 含且仅含偶数个质因数因子且无完全平方数因子 的因子的倍数
考虑到 μ(N) 的定义 对于满足第一个条件的 N=p11p12p13...p1k(kmod2==1) μ(N)=1
而满足第二个条件的 N=p11p12p13...p1k(kmod2==0) μ(N)=1

因此最后的结果即为 res=Nk=1μ(k)Nk2

附上参考代码

#include <iostream>
#include <cstdio>
using namespace std;

int prime[50005],cnt=0,mu[50005];
bool mark[50005];

void MU()
{
    mu[1]=1;
    for(int i=2;i<=50000;i++)
    {
        if(!mark[i])prime[++cnt]=i,mu[i]=-1;
        for(int j=1;j<=cnt&&prime[j]*i<=50000;j++)
        {
            mark[i*prime[j]]=1;
            if(i%prime[j]==0){mu[i*prime[j]]=0;break;}
            else mu[i*prime[j]]=-mu[i];
        }
    }
}

long long CAL(long long x)
{
    long long res=0;
    for(int i=1;i*i<=x;i++)
        res+=mu[i]*x/(i*i);
    return res;
}

int main()
{
//  freopen("In.txt","r",stdin);
//  freopen("Out.txt","w",stdout);
    long long T,L,R,mid,k,ans;
    MU();
    scanf("%lld",&T);
    while(T--)
    {
        scanf("%lld",&k);
        L=k;R=1644934082;
        while(L<R)
        {
            mid=L+R+1>>1;
            if(CAL(mid)>=k)R=mid;
            else L=mid+1;
        }
        printf("%lld\n",R);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值