• bzoj2440 [中山市选2011]完全平方数


    bzoj2440 [中山市选2011]完全平方数

    求第 \(k\) 个不是完全平方数的正整数倍的数,\(T\) 组询问

    \(T\leq50,\ k\leq10^9\)

    容斥+莫比乌斯函数


    首先二分答案,将原问题转化为

    \([1,\ n]\) 中不是完全平方数的正整数倍的数的个数

    SP4168 SQFREE - Square-free integers

    现在考虑原问题的逆问题,即 \([1,\ n]\) 中是完全平方数的正整数倍的数的个数,由容斥原理得到 $$\lfloor\frac{n}{22}\rfloor+\lfloor\frac{n}{32}\rfloor+\lfloor\frac{n}{52}\rfloor-\lfloor\frac{n}{62}\rfloor+\lfloor\frac{n}{72}\rfloor-\lfloor\frac{n}{102}\rfloor+\cdots$$

    \(\therefore\) 原式 \(=\) $$n-\lfloor\frac{n}{22}\rfloor-\lfloor\frac{n}{32}\rfloor-\lfloor\frac{n}{52}\rfloor+\lfloor\frac{n}{62}\rfloor-\lfloor\frac{n}{72}\rfloor+\lfloor\frac{n}{102}\rfloor+\cdots$$

    现在观察 \(\lfloor\frac{n}{i^2}\rfloor\) 的系数:$$1\times n+(-1)\times\lfloor\frac{n}{22}\rfloor+(-1)\times\lfloor\frac{n}{32}\rfloor+0\times\lfloor\frac{n}{42}\rfloor+(-1)\times\lfloor\frac{n}{52}\rfloor+1\times\lfloor\frac{n}{62}\rfloor+(-1)\times\lfloor\frac{n}{72}\rfloor+0\times\lfloor\frac{n}{8^2}\rfloor+\cdots$$

    有没有想到那个熟悉的函数 $$\mu(i)=\begin{cases}1&&(i=1)\(-1)^k&&(i=\prod p_k,\ p_k\in prime)\0&&other\end{cases}$$

    易证原式 \(\lfloor\frac{n}{i^2}\rfloor\) 的系数即为 \(\mu(i)\)

    即求 $$\displaystyle\sum_{i=1}^\sqrt n \mu(i)\lfloor\frac{n}{i^2}\rfloor$$

    可以发现最终答案 \(ans\) 满足 \(k\le ans\leq 2\times k\)

    因此时间复杂度 \(O(T\sqrt k\log k)\),空间复杂度 \(O(\sqrt k)\)

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    const int maxn = 5e4 + 10;
    int T, n, tot, p[maxn], mu[maxn];
    
    void sieve() {
      int t = 45000; mu[1] = 1;
      for (int i = 2; i <= t; i++) {
        if (!p[i]) mu[i] = -1, p[++tot] = i;
        for (int j = 1; j <= tot && i * p[j] <= t; j++) {
          p[i * p[j]] = 1;
          if (i % p[j] == 0) {
            mu[i * p[j]] = 0; break;
          }
          mu[i * p[j]] = -mu[i];
        }
      }
    }
    
    bool check(int x) {
      int t = sqrt(x), res = x;
      for (int i = 2; i <= t; i++) {
        res += x / (i * i) * mu[i];
      }
      return res < n;
    }
    
    int main() {
      scanf("%d", &T), sieve();
      while (T--) {
        scanf("%d", &n);
        ll l = n, r = n << 1, mid, res;
        while (l <= r) {
          check(mid = (l + r) >> 1) ? l = mid + 1 : r = (res = mid) - 1;
        }
        printf("%d\n", (int)res);
      }
      return 0;
    }
    
  • 相关阅读:
    oracle 添加用户
    oracle---存储结构及其之间的关系和创建数据库
    oracle---临时表空间
    对字符串进行加密解密知识
    面向对象---函数重复---原型
    Ajax
    sqlHelper+app.config
    sqlHelper ---转载
    web.config中的连接字符串 ---关于 providerName 特性---转载
    SQL中的cast()函数--转载
  • 原文地址:https://www.cnblogs.com/Juanzhang/p/10341603.html
Copyright © 2020-2023  润新知