【BZOJ2440&&2986】徹底平方數

題意:求第k個無平方因子數是多少ios

無平方因子數(square-free number),即質因數分解以後全部質因數的次數都爲1的數ide

膜拜Po姐姐函數

二分答案 設二分後值爲x 咱們考慮前x個數中是否含有超過k個不是平方因子的數spa

咱們考慮平方因子必定含有至少一個質數的平方 debug

那麼考慮容斥,即質數平方個數爲0的數的個數-質數平方個數爲1的數的個數+質數平方個數爲2的數的個數-……code

公式表示的話 設有p個素數並且選擇了i個素數是平方,且任選i個素數的乘積爲d,獲得公式blog

$f(x)=\sum_{i=0}^{p}(-1)^i \lfloor \frac{n}{d^{2}}  \rfloor(d爲任意i個素數相乘的積)$ip

發現d最多選擇到$\sqrt{ n }$ 那麼咱們能夠考慮直接枚舉d 因而問題變成了如何快速判斷d的貢獻get

莫比烏斯函數便是。string

而後根據莫比烏斯函數的定義式,將式子化爲$f(x)=\sum_{d=1}^{\sqrt{x}} \mu (d) \lfloor \frac{n}{d^{2}} \rfloor $

因此咱們枚舉根號n內的全部答案 帶入計算便可 複雜度$O(\sqrt{n}log{n})$

/*To The End Of The Galaxy*/
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<iomanip>
#include<bitset>
#include<stack>
#include<map>
#include<set>
#include<cmath>
#include<complex>
#define debug(x) cerr<<#x<<"="<<x<<endl
#define INF 0x7f7f7f7f
#define llINF 0x7fffffffffffll
#define P(x,y) (((x-1)*c)+y)
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
inline int init()
{
    int now=0,ju=1;char c;bool flag=false;
    while(1)
    {
        c=getchar();
        if(c=='-')ju=-1;
        else if(c>='0'&&c<='9')
        {
            now=now*10+c-'0';
            flag=true;
        }
        else if(flag)return now*ju;
    }
}
inline long long llinit()
{
    long long now=0,ju=1;char c;bool flag=false;
    while(1)
    {
        c=getchar();
        if(c=='-')ju=-1;
        else if(c>='0'&&c<='9')
        {
            now=now*10+c-'0';
            flag=true;
        }
        else if(flag)return now*ju;
    }
}
int n=100000,prime[100005],cnt,mu[100005];
bool vis[100005];
void getmu()
{
    mu[1]=1;
    for(int i=2;i<=n;i++)
    {
        if(!vis[i])
        {
            vis[i]=1;
            mu[i]=-1;
            ++cnt;prime[cnt]=i;
        }
        for(int j=1;j<=cnt&&prime[j]*i<=n;j++)
        {
            vis[i*prime[j]]=1;
            if(i%prime[j]==0)
            {
                mu[i*prime[j]]=0;
                break;
            }
            mu[i*prime[j]]=-mu[i];
        }
    }
}
#define mid ((l+r)>>1)
int cas;
ll l,r;
ll calc(ll x)
{
    ll res=0;
    for(int i=1;i*i<=x;i++)
    {
        res+=x/(i*i)*mu[i];
    }
    return res;
}
int main()
{
    cas=init();
    getmu();
    int k;
    ll ans;
    for(int i=1;i<=cas;i++)
    {
        k=init();
        l=1,r=k*2;
        while(l<=r)
        {
            if(calc(mid)>=k)
            {
                ans=mid;
                r=mid-1;
            }
            else l=mid+1;
        }
        printf("%lld\n",ans);
    }
    return 0;
}
View Code
相關文章
相關標籤/搜索