zoukankan      html  css  js  c++  java
  • bzoj 2440 完全平方数 【莫比乌斯函数】

    题目

    题意:第Ki 个不是完全平方数的正整数倍的数。

    对于一个数t,t以内的数里的非完全平方数倍数的个数:num=1的倍数的数量−一个质数平方数(9,25,49...)的倍数的数量+两个质数的积平方数(36,100,225...)的数量−三个质数balabala……

    所以   (然而这一坨是怎么推出来的呢?)

    u(i)就是莫比乌斯函数

    求莫比乌斯函数代码:

    //递推
    ll mu[100005];
    void mobius(ll mn)
    {
        mu[1]=1;
        for(ll i=1;i<=mn;i++){
            for(ll j=i+i;j<=mn;j+=i){
                mu[j]-=mu[i];
            }
        }
    }
    
    //main
    	mobius(100000);
    //线性筛法求莫比乌斯函数  
    bool check[MAXN+10];  
    int prime[MAXN+10];  
    int mu[MAXN+10];  
    void Moblus()  
    {  
        memset(check,false,sizeof(check));  
        mu[1] = 1;  
        int tot = 0;  
        for(int i = 2; i <= MAXN; i++)  
        {  
            if( !check[i] ){  
                prime[tot++] = i;  
                mu[i] = -1;  
            }  
            for(int j = 0; j < tot; j++)  
            {  
                if(i * prime[j] > MAXN) break;  
                check[i * prime[j]] = true;  
                if( i % prime[j] == 0){  
                    mu[i * prime[j]] = 0;  
                    break;  
                }else{  
                    mu[i * prime[j]] = -mu[i];  
                }  
            }  
        }  
    }
    

    所以代码:

    #include <cstdio>
    #include <cmath>
    typedef long long ll;
    const ll M=100001;
    ll t,n,miu[M],pri[M],bo[M],ans;
    void makemiu(){
        miu[1]=1;
        for (ll i=2;i<M;i++){
            if (!bo[i]){
                pri[++pri[0]]=i;
                miu[i]=-1;
            }
            for (ll j=1;j<=pri[0] && pri[j]*i<M;j++){
                bo[i*pri[j]]=1;
                if (i%pri[j]==0){
                    miu[i*pri[j]]=0;
                    break;
                }else miu[i*pri[j]]=-miu[i];
            }
        }
    }
    ll check(ll t){
        ll sq=(int)sqrt(t),res=0;
        for (ll i=1;i<=sq;i++)
        res=res+miu[i]*(t/(i*i));
        return res;
    }
    ll getans(ll t){
        ll l=0,r=t*2,mid;
        while (l+1<r){
            mid=(l+r)/2;
            if (check(mid)<t) l=mid;
            else r=mid;
        }
        return r;
    }
    int main(){
        scanf("%I64d",&t);
        makemiu();
        for (ll i=1;i<=t;i++){
            scanf("%I64d",&n);
            printf("%I64d
    ",getans(n));
        }
    }
  • 相关阅读:
    多读者多写者的无锁队列
    PCI设备的地址空间
    交换机能不能连接不同的网段?
    VMware Workstation的三种网络连接模式
    Linux内存寻址和内存管理
    Fragment基础信息传递
    Android Studio获取SHA1和MD5方法
    AppCan学习笔记数据存储及listview简单应用
    Fragment基础生命周期
    Fragment基础创建
  • 原文地址:https://www.cnblogs.com/qie-wei/p/10160155.html
Copyright © 2011-2022 走看看