bzoj 2440 容斥原理

  首先根据样例或者自己打表大概可以知道,对于询问k,答案不会超过k<<1,那么我们就可以二分答案,求当前二分的值内有多少个数不是完全平方数的倍数,这样就可以了,对于每个二分到的值x,其中完全平方数的倍数的个数为Σmiu(i)*(n/(i*i)),原理就是容斥,但是根据莫比乌斯反演应该也是能推出来的(我没推出来)。

  反思:开始莫比乌斯函数筛错了,后来的时候没用longlong,导致二分的时候int溢出了,这样就死循环了,找了半天错。

/**************************************************************
    Problem: 2440
    User: BLADEVIL
    Language: C++
    Result: Accepted
    Time:1164 ms
    Memory:2456 kb
****************************************************************/
 
//By BLADEVIL
#include <cstdio>
#include <iostream>
#include <cmath>
#define maxn 50010
 
using namespace std;
 
long long mindiv[maxn],prim[maxn],miu[maxn];
 
void prepare()
{
    miu[1]=1;
    for (long long i=2;i<=50000;i++)
    {
        if (!mindiv[i])
        {
            prim[++prim[0]]=i;
            miu[i]=-1;
        }
        for (long long j=1;j<=prim[0]&&prim[j]*i<=50000;j++)
        {
            mindiv[i*prim[j]]=prim[j];
            if (!(i%prim[j]))
            {
                miu[i*prim[j]]=0;
                break;
            }
            miu[i*prim[j]]=-miu[i];
        }
    }
}
 
long long calc(long long x)
{
    long long tot=0,t;
    for (long long i=1;i<=sqrt(x);i=t+1) 
    {
        t=x/(x/(i*i)); t=sqrt(t);
        //printf("%d %d
",i,t);
        tot+=(miu[t]-miu[i-1])*(x/(i*i));
        //printf("%d
",tot);
        //printf("%d %d
",miu[t],miu[i-1]);
    }
    return tot;
}
 
int main()
{   
    prepare();
    for (long long i=1;i<=50000;i++) miu[i]+=miu[i-1];
    //printf("%d",calc(1));
    //for (long long i=1;i<=100;i++) printf("%d ",miu[i]);
    long long task;
    scanf("%lld",&task);
    while (task--)
    {
        long long l=1ll,r,n,ans;
        scanf("%lld",&n);
        r=n<<1;
        while (l<=r)
        {
            long long mid=(l+r)>>1;
            //printf("%d %d %d
",l,r,mid);
            if (calc(mid)>=n)
            {
                ans=mid;
                r=mid-1ll;
            } else l=mid+1ll;
            //printf("%d %d %d
",l,r,mid);
        }
        printf("%lld
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/BLADEVIL/p/3554701.html