zoukankan      html  css  js  c++  java
  • 【[SDOI2018]旧试题】

    一道很有趣的题目。
    题目大意:求

    [sum_{i=1}^A sum_{j=1}^B sum_{k=1}^C sigma_0(ijk) ]

    因为

    [sigma_0(ijk)=sum_{p|i}sum_{q|j}sum_{h|k}[epsilon( ext{gcd}(p,q))][epsilon( ext{gcd}(p,h))][epsilon( ext{gcd}(q,h))] ]

    所以原式=

    [sum_{i=1}^Asum_{j=1}^Bsum_{k=1}^Csum_{p|i}sum_{q|j}sum_{h|k}[epsilon( ext{gcd}(p,q))][epsilon( ext{gcd}(p,h))][epsilon( ext{gcd}(q,h))] ]

    交换枚举顺序,枚举因数

    [sum_{p=1}^Asum_{q=1}^Bsum_{h=1}^C lfloor frac{A}{p} floor lfloor frac{B}{q} floor lfloor frac{C}{h} floor [epsilon( ext{gcd}(p,q))][epsilon( ext{gcd}(p,h))][epsilon( ext{gcd}(q,h))]]

    把后面那团( ext{gcd})(mu)函数换掉

    [sum_{p=1}^Asum_{q=1}^Bsum_{h=1}^C sum_{x| ext{gcd}(p,q)}mu(x) sum_{y| ext{gcd}(p,h)} mu(y) sum_{z| ext{gcd}(q,h)}mu(z) ]

    再换一下枚举顺序

    [sum_{x=1}^{ ext{min(A,B)}}mu(x) sum_{y=1}^{ ext{min}(A,C)}mu(y) sum_{z=1}^{ ext{min}(B,C)}mu(z) sum_{x|p & & y|p} lfloor frac{A}{p} floor sum_{x|q & & z|q} lfloor frac{B}{q} floor sum_{y | h & & z|h} lfloor frac{C}{h} floor ]

    [sum_{x=1}^{ ext{min(A,B)}}mu(x) sum_{y=1}^{ ext{min}(A,C)}mu(y) sum_{z=1}^{ ext{min}(B,C)}mu(z) sum_{ ext{lcm}(x,y)|p} lfloor frac{A}{p} floor sum_{ ext{lcm}(x,z)|q} lfloor frac{B}{q} floor sum_{ ext{lcm}(y,z)|h} lfloor frac{C}{h} floor ]

    然后我们发现这个式子其实不一样的地方只有两部分...
    形如(sum limits_{a|b}^c lfloor frac{c}{b} floor)的那三项可以(mathcal{O}(n log n))预处理出来。
    接下来才是这道题的精髓。
    (mathcal{O}(n^3))枚举三元组((x,y,z))的同时,我们可以发现有很多时候他们的情况是(0)
    1:(mu(x)=0)(mu(y)=0)(mu(z)=0)
    2:若(sum limits_{a|b}^c lfloor frac{c}{b} floor)中的(a)大于(c),则这个式子的贡献一定为(0),也就是说当( ext{lcm}(x,y) geq A)( ext{lcm}(x,z) geq B)( ext{lcm}(y,z) geq C)时,这个式子的贡献一定为(0)
    于是我们就可以枚举最大公约数(g),使得(u=i imes g,v = j imes g, mu(u) eq 0,mu(v) eq 0)并保证(i)(j)互质且( ext{lcm}(u,v)=i imes j imes g leq ext{max}(A,B,C)),连边((u,v)),最后统计三元环的时候顺便计数就好了。
    因为(mathsf{s{color{red}hadowice1984}})大佬告诉我们边数最多只有(760741)条,所以(m sqrt m)是可过的。
    代码:

    #include <bits/stdc++.h>
    
    typedef long long ll;
    const int N = 1e5 + 200;
    const ll mod = 1e9 + 7;
    typedef std::pair<int, int> pii;
    
    int n, m, i, j, k, prim_tot, T, A, B, C, mx, mn, cnte;
    ll _1[N], _2[N], _3[N];
    int vis[N], deg[N];
    int mu[N], prim[N]; 
    bool _vis[N];
    ll ans;
    
    inline void sieve(int n) {
      mu[1] = 1;
      for (int i = 2; i <= n; i++) {
        if (!_vis[i]) prim[++prim_tot] = i, mu[i] = -1;
        for (int j = 1; j <= prim_tot && i * prim[j] <= n; j++) {
          _vis[i * prim[j]] = 1;
          if (i % prim[j] == 0) break;
          else mu[i * prim[j]] = -mu[i];
        }
      }
    }
    
    struct edge {
      int u, v, w;
      edge() { u = v = w = 0; }
      edge(int _u, int _v, int _w) {
        u = _u, v = _v, w = _w;
      }
    } edges[N << 4];
    
    std::vector<pii> G[N];
    
    inline void init() {
      scanf("%d %d %d", &A, &B, &C), ans = 0, cnte = 0;
      mx = std::max(std::max(A, B), C);
      mn = std::min(std::min(A, B), C);
      for (int i = 1; i <= mx; i += 8) {
        _1[i] = _1[i + 1] = _1[i + 2] = _1[i + 3] = _1[i + 4] = _1[i + 5] = _1[i + 6] = _1[i + 7] = 0;
        _2[i] = _2[i + 1] = _2[i + 2] = _2[i + 3] = _2[i + 4] = _2[i + 5] = _2[i + 6] = _2[i + 7] = 0;
        _3[i] = _3[i + 1] = _3[i + 2] = _3[i + 3] = _3[i + 4] = _3[i + 5] = _3[i + 6] = _3[i + 7] = 0;
        deg[i] = deg[i + 1] = deg[i + 2] = deg[i + 3] = deg[i + 4] = deg[i + 5] = deg[i + 6] = deg[i + 7] = 0;
      }
      for (int i = 1; i <= mx; i++) G[i].clear();
      for (int i = 1; i <= A; i++) {
        for (int j = i; j <= A; j += i)
          _1[i] += A / j;
      }
      for (int i = 1; i <= B; i++) {
        for (int j = i; j <= B; j += i) 
          _2[i] += B / j;
      }
      for (int i = 1; i <= C; i++) {
        for (int j = i; j <= C; j += i)
          _3[i] += C / j;
      }
    }
    inline void solve() {
      for (int i = 1; i <= mn; i++) {
        if (mu[i]) ans += 1ll * mu[i] * mu[i] * mu[i] * _1[i] * _2[i] * _3[i];
      }
      for (int g = 1; g <= mx; g++) {
        for (int i = 1; i * g <= mx; i++) {
          if (!mu[i * g]) continue;
          for (int j = i + 1; 1ll * i * j * g <= mx; j++) {
            if (mu[j * g] && std::__gcd(i, j) == 1) {
              int u = i * g, v = j * g, lcm = i * j * g;
              int p = mu[u] * mu[u] * mu[v], q = mu[u] * mu[v] * mu[v];
              ans += p * (_1[u] * _2[lcm] * _3[lcm] + _1[lcm] * _2[u] * _3[lcm] + _1[lcm] * _2[lcm] * _3[u]);
              ans += q * (_1[v] * _2[lcm] * _3[lcm] + _1[lcm] * _2[v] * _3[lcm] + _1[lcm] * _2[lcm] * _3[v]);
              deg[u]++, deg[v]++;
              edges[++cnte] = edge(u, v, lcm);
            }
          }
        }
      }
      for (int i = 1; i <= cnte; i++) {
        int u = edges[i].u, v = edges[i].v, w = edges[i].w;
        if (deg[u] < deg[v] || (deg[u] == deg[v] && u > v)) std::swap(u, v);
        G[u].push_back(std::make_pair(v, w));
      }
      for (int k = 1; k <= mx; k++) {
        if (!mu[k]) continue;
        int SZ = G[k].size();
        for (int i = 0; i < SZ; i++) vis[G[k][i].first] = G[k][i].second;
        for (int i = 0; i < SZ; i++) {
          int v = G[k][i].first, w = G[k][i].second;
          if (!mu[v]) continue;
          for (int j = 0, _SZ = G[v].size(); j < _SZ; j++) {
            int vv = G[v][j].first;
            if (!vis[vv]) continue;
            int wyz = G[v][j].second, wxz = vis[vv], mmu = mu[k] * mu[v] * mu[vv];
            if (!mmu) continue;
            ans += mmu * (_1[w] * _2[wyz] * _3[wxz] + _1[w] * _2[wxz] * _3[wyz] 
                        + _1[wyz] * _2[w] * _3[wxz] + _1[wyz] * _2[wxz] * _3[w]
                        + _1[wxz] * _2[w] * _3[wyz] + _1[wxz] * _2[wyz] * _3[w]);
          }
        }
        for (int i = 0; i < SZ; i++) vis[G[k][i].first] = 0;
      }
      printf("%lld
    ", ans % mod);
    }
    
    int main() {
      sieve(100000);
      scanf("%d", &T);
      while (T--) init(), solve();
      return 0;
    }
    
    
  • 相关阅读:
    php分页类 (来源网络)
    symfony2 symofny3中得到get post session cookies的方法
    symfony route参数
    Symfony2同步数据库的数据表
    mysql中SQL执行过程详解与用于预处理语句的SQL语法
    使用MySQL命令行新建用户并授予权限的方法
    抽象类和接口的区别
    Yaf 使用遇到的坑
    Mysql 常用引擎的特点及选择使用策略
    定时任务 Crontab命令 详解
  • 原文地址:https://www.cnblogs.com/Sai0511/p/12389708.html
Copyright © 2011-2022 走看看