zoukankan      html  css  js  c++  java
  • bzoj2440 完全平方数 莫比乌斯值+容斥+二分

    莫比乌斯值+容斥+二分
    /**
    题目:bzoj2440 完全平方数
    链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2440
    题意:求第k个小x数。小x数是指不存在某个素因子次数>=2。1也是小x数。
    
    思路:二分x,求[1,x]有多少个小x数。如果一个数是某个素数的平方的倍数,那么不是小x数。
    
    所以要减去。2^2的倍数, 3^2的倍数, 5^2的倍数. 由于减去2的平方的倍数和3的平方的倍数把6的平方的倍数多减去了一次。所以要加回去。
    
    ans = sigma[1,sqrt(x)] mu[i]*x/i/i ;
    
    
    */
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <set>
    #include <iostream>
    #include <vector>
    #include <map>
    using namespace std;
    typedef long long LL;
    #define ms(x,y) memset(x,y,sizeof x)
    typedef pair<int, int> P;
    const LL INF = 1e10;
    const int mod = 1e9 + 7;
    const int maxn = 1e5 + 100;
    int prime[maxn], tot, not_prime[maxn];
    int mu[maxn];
    map<LL,LL> mp;
    void get()
    {
        mu[1] = 1;
        tot = 0;
        for(int i = 2; i < maxn; i++){
            if(!not_prime[i]){
                prime[++tot] = i;
                mu[i] = -1;
            }
            for(int j = 1; prime[j]*i<maxn; j++){
                not_prime[prime[j]*i] = 1;
                if(i%prime[j]==0){
                    mu[prime[j]*i] = 0;
                    break;
                }
                mu[prime[j]*i] = -mu[i];
            }
        }
    }
    
    LL solve(LL x)
    {
        LL ans = 0;
        for(LL i = 1; i*i<=x; i++){
            ans += mu[i]*x/i/i;
        }
        return ans;
    }
    int main()
    {
        //freopen("in.txt","r",stdin);
        int T;
        int k;
        get();
        mp.clear();
        cin>>T;
        while(T--)
        {
            scanf("%d",&k);
            LL lo = 1, hi = INF, mid;
            LL ans = INF;
            while(lo<=hi){
                mid = (lo+hi)/2;
                if(mp[mid]!=0){///加了map后省了一半的时间,注意使用场景。有时候可能不能用。有时候时间增大。
                    if(mp[mid]>=k){
                        ans = mid;
                        hi = mid-1;
                    }else
                    {
                        lo = mid+1;
                    }
                    continue;
                }
                if((mp[mid]=solve(mid))>=k){
                    ans = mid;
                    hi = mid-1;
                }else lo = mid+1;
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    WC命令
    dcoker machine
    linux命令
    Valgrind 检测程序内存使用
    golang flag
    面试之---二叉树的遍历
    FFMpeg 版本错误
    C++中namespace的使用
    QT之QStatusBar
    建立ftp服务器和客户端
  • 原文地址:https://www.cnblogs.com/xiaochaoqun/p/7360157.html
Copyright © 2011-2022 走看看