zoukankan      html  css  js  c++  java
  • Edu Codeforces Round 45 选做

    Problem G. GCD Counting

    考虑差分,记录每一个答案 (ans_i)(gcd)(i) 的倍数的方案总数。

    每次只需要枚举出连通块,然后直接计算即可。

    时间复杂度 (O(nsqrt n))

    #pragma GCC optimze("O2")
    
    #include <bits/stdc++.h>
    
    using namespace std;
    
    template <typename T> 
    void read(T& x) {
      x = 0; 
      char ch = 0;
      for (; !isdigit(ch); ch = getchar());
      for (; isdigit(ch); ch = getchar()) {
        x = x * 10 + (ch & 15);
      }
    }
    
    const int N = 2e5 + 5;
    
    struct edge {
      int to, nxt;
    } e[N << 1];
    
    int head[N];
    int edge_cnt;
    int a[N];
    vector<int> fac[N];
    int vis[N];
    long long ans[N];
    int sz, dg;
    
    void add_edge(int u, int v) {
      e[++edge_cnt] = (edge){v, head[u]};
      head[u] = edge_cnt; 
    }
    
    void divide(int x, int id) {
      for (int i = 1; i * i <= x; ++i) {
        if (x % i == 0) {
          fac[i].emplace_back(id); 
          if (i * i != x) {
            fac[x / i].emplace_back(id); 
          }
        }
      }
    }
    
    void dfs(int u, int fa) {
      ++sz;
      vis[u] = dg; 
      for (int i = head[u]; i; i = e[i].nxt) {
        int v = e[i].to;
        if (v != fa && a[v] % dg == 0) {
          dfs(v, u); 
        }
      }
    }
    
    int main() {
      int n;
      read(n); 
      for (int i = 1; i <= n; ++i) {
        cin >> a[i];
        divide(a[i], i); 
      }
      for (int i = 1; i < n; ++i) {
        int u, v;
        read(u), read(v); 
        add_edge(u, v); 
        add_edge(v, u); 
      }
      for (dg = 1; dg <= 200000; ++dg) { 
        for (int i = 0, m = fac[dg].size(); i < m; ++i) {
          if (vis[fac[dg][i]] != dg) { 
            sz = 0; 
            dfs(fac[dg][i], 0); 
            ans[dg] += (long long)sz * (sz - 1) / 2 + sz;
          }
        }
      }
      for (int i = 200000; i >= 1; --i) {
        for (int j = i + i; j <= 200000; j += i) {
          ans[i] -= ans[j]; 
        }
      }
      for (int i = 1; i <= 200000; ++i) {
        if (ans[i]) {
          printf("%d %I64d
    ", i, ans[i]); 
        }
      }
      return 0; 
    }
    
  • 相关阅读:
    JZOJ 3034. 【NOIP2012模拟10.17】独立集
    JZOJ 3035. 【NOIP2012模拟10.17】铁轨
    JZOJ 1259. 牛棚安排
    数位DP JZOJ 3316. 非回文数字
    JZOJ 3046. 游戏
    JZOJ 3013. 填充棋盘
    debian 安装oracle提供的java8
    java 汉字转拼音 PinYin4j
    debian ssh设置root权限登陆 Permission denied, please try again
    java并发下订单生成策略
  • 原文地址:https://www.cnblogs.com/chhokmah/p/13517111.html
Copyright © 2011-2022 走看看