zoukankan      html  css  js  c++  java
  • [bzoj3994][SDOI2015]约数个数和-数论

    Brief Description

    计算(sum_{ileqslant n}sum_{jleqslant m}sigma_0(ij)).

    Algorithm Design

    首先证明一个结论

    [d(ij) = sum_{ileqslant n}sum_{j leqslant m}[(i,j)=1] ]

    我们不显式地证明它, 仅仅直观地考虑每个质数对于答案的贡献就好.
    有了这个结论我们开始推式子:

    [egin{aligned} sum_{ileqslant n}sum_{jleqslant m}sigma_0(ij) & = sum_{ileqslant n}sum_{jleqslant m} sum_{a|i} sum_{b|j} [(i,j)=1]\ & =sum_{ileqslant n}sum_{jleqslant m}sum_{a|i}sum_{b|j}sum_{x|(i,j)}mu(x)\& =sum_{ileqslant n}sum_{j leqslant m}sum_{x|i+j}mu(x)sigma_0(frac ix)sigma_0(frac jx) \ &=sum_{x leqslant n} mu(x)sum_{i leqslant lfloor frac nx floor} sigma_0(i)sum_{j leqslant lfloor frac mx floor}sigma_0(j) end{aligned} ]

    有了最后的式子, 我们就可以开始乱搞了.
    复杂度(O(n+Tsqrt n))

    Code

    #include <algorithm>
    #include <cctype>
    #include <cstdio>
    #define ll long long
    const int maxn = 50000 + 10;
    int prime[maxn], tot;
    int mu[maxn], sigma[maxn], summu[maxn];
    ll sumsigma[maxn];
    bool check[maxn];
    int read() {
      int x = 0, f = 1;
      char ch = getchar();
      while (!isdigit(ch)) {
        if (ch == '-')
          f = -1;
        ch = getchar();
      }
      while (isdigit(ch)) {
        x = x * 10 + ch - '0';
        ch = getchar();
      }
      return x * f;
    }
    void shake() {
      int minPrimeCnt[maxn];
      mu[1] = 1, sigma[1] = 1;
      for (int i = 2; i < maxn; i++) {
        if (!check[i]) {
          prime[tot++] = i;
          mu[i] = -1;
          sigma[i] = 2;
          minPrimeCnt[i] = 1;
        }
        for (int j = 0; j < tot; j++) {
          int x = i * prime[j];
          if (x >= maxn)
            break;
          check[x] = 1;
          if (i % prime[j] == 0) {
            mu[x] = 0;
            minPrimeCnt[x] = minPrimeCnt[i] + 1;
            sigma[x] = sigma[i] / (minPrimeCnt[i] + 1) * (minPrimeCnt[x] + 1);
            break;
          } else {
            mu[x] = -mu[i];
            sigma[x] = sigma[i] << 1;
            minPrimeCnt[x] = 1;
          }
        }
      }
      summu[0] = 0;
      for (int i = 1; i < maxn; i++)
        summu[i] = summu[i - 1] + mu[i];
      for (int i = 1; i < maxn; i++)
        sumsigma[i] = sumsigma[i - 1] + sigma[i];
    }
    ll F(int n, int m) {
      if (n > m)
        std::swap(n, m);
      ll ans = 0;
      for (int i = 1, last = 1; i <= n; i = last + 1) {
        last = std::min(n / (n / i), m / (m / i));
        ans += (summu[last] - summu[i - 1]) * sumsigma[n / i] * sumsigma[m / i];
      }
      return ans;
    }
    int main() {
    #ifndef ONLINE_JUDGE
      freopen("input", "r", stdin);
    #endif
      shake();
      int kase = read();
      while (kase--) {
        int n = read(), m = read();
        printf("%lld
    ", F(n, m));
      }
      return 0;
    }
    
  • 相关阅读:
    TensorFlow 学习(4)——MNIST机器学习进阶
    TensorFlow 学习(3)——MNIST机器学习入门
    TensorFlow 学习(2)——正式起步
    TensorFlow 学习(1)——第一个程序:线性回归
    OpenCV学习笔记(15)——更多的轮廓函数
    OpenCV学习笔记(14)——轮廓的性质
    OpenCV学习笔记(13)——轮廓特征
    OpenCV学习笔记(12)——OpenCV中的轮廓
    机器学习
    机器学习- Attention Model结构解释及其应用
  • 原文地址:https://www.cnblogs.com/gengchen/p/6594867.html
Copyright © 2011-2022 走看看