zoukankan      html  css  js  c++  java
  • 「BZOJ 2440」完全平方数「数论分块」

    题意

    (T)组数据,每次询问第(k)个无平方因子的数((1)不算平方因子),(Tleq 50,kleq 10^9)

    题解

    (k)的范围很大,枚举肯定不行,也没什么奇妙性质,于是可以想到二分。

    二分的话我们需要实现一个函数(f(n))表示(n)以内的数中无平方因子的数个数

    这十分经典,相当于求(f(n)=sum_{i=1}^nmu^2(i))

    解法就是:我们考虑一个质数(p)(p^2)的倍数都不满足要求,也就是说答案得减去(lfloor frac{n}{p^2} floor)。但显然这个会重复,需要容斥。就是说一个数(x=p_1p_2..p_k),答案得加上((-1)^k lfloor frac{n}{x^2} floor)

    然后就会神奇地发现对于一个正整数(i)它的贡献的系数恰好就是(mu(i))

    也就是说答案就是(sum_{i=1}^{sqrt n} mu(i) lfloor frac{n}{i^2} floor) 。预处理(mu)前缀和然后数论分块就好。

    分块那里有一点小细节,与常见数论分块不大一样。还有二分的右边界,可以设为(k)(4)倍,实际上观察样例就可以猜到(2)倍就可以了。

    复杂度为大致为(O(Tsqrt klog k))

    #include <algorithm>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    
    typedef long long ll;
    
    const int N = 64000;
    
    int mu[N + 5], p[N + 5], cnt;
    bool tag[N + 5];
    
    void sieve(int n) {
        mu[1] = 1;
        for(int i = 2; i <= n; i ++) {
            if(!tag[i]) {
                p[cnt ++] = i;
                mu[i] = -1;
            }
            for(int j = 0; j < cnt; j ++) {
                if(i * p[j] > n) break ;
                tag[i * p[j]] = 1;
                if(i % p[j] == 0) {
                    mu[i * p[j]] = 0;
                    break ;
                }
                mu[i * p[j]] = - mu[i];
            }
        }
        for(int i = 2; i <= n; i ++) mu[i] += mu[i - 1];
    }
    
    ll calc(ll n) {
        ll x = (ll) sqrt(n), ans = 0;
        for(ll i = 1, j; i * i <= n; i = j + 1) {
            j = sqrt(n / (n / (i * i)));
            if(j > x) j = x;
            ans += (mu[j] - mu[i - 1]) * (n / (i * i));
        }
        return ans;
    }
    
    int main() {
        sieve(N);
        int t, k; scanf("%d", &t);
        while(t --) {
            scanf("%d", &k);
            ll l = 1, r = 4e9, mid, ans = -1;
            while(l <= r) {
                mid = (l + r) >> 1;
                if(calc(mid) >= k) r = (ans = mid) - 1;
                else l = mid + 1;
            }
            printf("%lld
    ", ans);
        }
        return 0;
    }
    
    
  • 相关阅读:
    MSP430的CAN通信发送
    Arduino 101/Genuino101使用-第2篇
    CC2541调试问题记录-第一篇
    STM32运行FreeRTOS出现prvTaskExitError错误死机
    Arduino 101/Genuino101使用-第一篇
    LAUNCHXL-28379D入门学习-第一篇
    蒸汽机的原理
    等高线相似性匹配
    cad转shapefile文件
    ArcGIS坐标转换
  • 原文地址:https://www.cnblogs.com/hongzy/p/10363064.html
Copyright © 2011-2022 走看看