CodeForces Gym 102056 简要题解

博客内容涵盖了CodeForces Gym 102056比赛中的多个题目,包括Exotic … Ancient City、Mysterious … Host、Heretical … Möbius等,通过详细讲解各种策略和解题思路,如并查集的应用、排列覆盖的分析、模欧拉函数的计算等,帮助读者理解并解决这些问题。
摘要由CSDN通过智能技术生成

Exotic … Ancient City

注意到值域很小,所以可以对每种 w w w 数只考虑 ≤ w \le w w 的边的连通块个数。维护一个大小为 2 n 2n 2n 的并查集,表示第 i i i 列和第 i + 1 i+1 i+1 列的连通性。考虑右移一列并查集的变化,如果在之前的并查集合并了集合 u + n , v + n u+n, v+n u+n,v+n ,那么在新的并查集上 u u u v v v 会变得连通。如果它们已经连通了,这条边就没用了;否则它们可能新增连通性,对后面有影响,以此类推即可。

#include <bits/stdc++.h>

using namespace std;

const int MAX = 30;

class dsu {
   
 public:
  vector<int> p;
  int n;

  dsu(int n): n(n) {
   
    p.resize(n);
    for (int i = 0; i < n; ++i) {
   
      p[i] = i;
    }
  }

  inline int find(int x) {
   
    while (x != p[x]) {
   
      x = p[x] = p[p[x]];
    }
    return x;
  }

  inline bool unite(int x, int y) {
   
    x = find(x);
    y = find(y);
    if (x == y) {
   
      return false;
    } else {
   
      p[x] = y;
      return true;
    }
  }
};

int main() {
   
#ifdef wxh010910
  freopen("input.txt", "r", stdin);
#endif
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  int n, m, q;
  cin >> n >> m >> q;
  vector<vector<pair<int, int>>> edges(MAX);
  while (q--) {
   
    int from, to, cost;
    cin >> from >> to >> cost;
    --from;
    --to;
    for (int i = cost; i < MAX; ++i) {
   
      edges[i].emplace_back(from, to);
    }
  }
  vector<long long> ans(m);
  for (int w = 0; w < MAX; ++w) {
   
    dsu p(n * 2);
    vector<long long> tag(m);
    vector<pair<int, int>> useful;
    for (auto e : edges[w]) {
   
      int x = p.find(e.first), y = p.find(e.second + n);
      if (x > y) {
   
        swap(x, y);
      }
      if (p.unite(x, y)) {
   
        ++tag[0];
        if (x >= n && y >= n) {
   
          useful.emplace_back(x - n, y - n);
        }
      }
    }
    for (int i = 1; i < m && !useful.empty(); ++i) {
   
      vector<pair<int, int>> new_useful;
      for (auto e : useful) {
   
        int x = p.find(e.first), y = p.find(e.second);
        if (x > y) {
   
          swap(x, y);
        }
        if (p.unite(x, y)) {
   
          if (x >= n && y >= n) {
   
            new_useful.emplace_back(x - n, y - n);
          }
        } else {
   
          --tag[i];
        }
      }
      swap(useful, new_useful);
    }
    for (int i = 1; i < m; ++i) {
   
      tag[i] += tag[i - 1];
    }
    for (int i = 1; i < m; ++i) {
   
      tag[i] += tag[i - 1];
    }
    for (int i = 0; i < m; ++i) {
   
      ans[i] += (long long) n * (i + 2) - 1 - tag[i];
    }
  }
  for (int i = 0; i < m; ++i) {
   
    cout << ans[i] << "\n";
  }
  return 0;
}

Mysterious … Host

考虑一个排列,用尽量少的段去覆盖它,分两种情况讨论:

  • 段数 ≥ 3 \ge 3 3 :划分方案是唯一的,连续段要么是整个排列要么在每段内部。其中段数为 3 3 3 无法构造,为 4 4 4 及以上可以构造。
  • 段数 = 2 =2 =2 :不妨假设 1 1 1 n n n 前面。如果长度为 i i i 的前缀正好是 [ 1 , i ] [1,i] [1,i] 的排列,那么划开 i i i i + 1 i+1 i+1 。连续段要么是若干个整段,要么是段内部。

所以 f ( n ) = ∑ k ≥ 2 ∏ ∑ i = 1 k a i = n f ( a i ) + ∑ k ≥ 4 ∏ ∑ i = 1 k a i = n f ( a i ) f(n) = \sum_{k\ge 2} \prod_{\sum_{i=1}^k a_i = n} f(a_i) + \sum_{k\ge 4} \prod_{\sum_{i=1}^k a_i = n} f(a_i) f(n)=k2i=1kai=nf(ai)+k4i=1kai=nf(ai)

#include <bits/stdc++.h>

using namespace std;

int main() {
   
#ifdef wxh010910
  freopen("input.txt", "r", stdin);
#endif
  int n, md;
  cin >> n >> md;
  auto add = [&](int &x, int y) {
   
    x += y;
    if (x >= md) {
   
      x -= md;
    }
  };
  auto mul = [&](int x, int y) {
   
    return (long long) x * y % md;
  };
  vector<vector<int>> sum(4, vector<int>(n + 1));
  vector<int> dp(n + 1);
  dp[1] = sum[0][1] = 1;
  for (int i = 2; i <= n; ++i) {
   
    for (int j = 1; j < i; ++j) {
   
      for (int k = 3; k; --k) {
   
        add(sum[k][i], mul(dp[j], sum[k - 1][i - j]));
        if (k == 3) {
   
          add(sum[k][i], mul(dp[j], sum[k][i - j]));
        }
      }
    }
    dp[i] = sum[3][i];
    for (int k = 3; k; --k) {
   
      add(dp[i], sum[k][i]);
    }
    sum[0][i] = dp[i];
  }
  for (int i = 1; i <= n; ++i) {
   
    cout << dp[i] << "\n";
  }
  return 0;
}

Heretical … Möbius

注意到 4 , 9 , 25 , 49 4, 9, 25, 49 4,9,25,49 的倍数的 μ \mu μ 一定为 0 0 0 ,所以枚举余数爆搜即可。对于一个合法的序列要搜索的东西不多,加个卡时判无解即可。

#include <bits/stdc++.h>

using namespace std;

const int N = 200;
const int MAX = 1e9;
const int SQ = sqrt(MAX);

int main() {
   
#ifdef wxh010910
  
您提供的链接是Codeforces的一个问题,问题编号为104377。Codeforces是一个知名的在线编程竞赛平台,经常举办各种编程比赛和训练。GymCodeforces的一个扩展包,用于组织私人比赛和训练。您提供的链接指向了一个问题的页面,但具体的问题内容和描述无法通过链接获取。如果您有具体的问题或需要了解关于Codeforces Gym的更多信息,请提供更详细的信息。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [http://codeforces.com/gym/100623/attachments E题](https://blog.csdn.net/weixin_30820077/article/details/99723867)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [http://codeforces.com/gym/100623/attachments H题](https://blog.csdn.net/weixin_38166726/article/details/99723856)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [CodeforcesPP:Codeforces扩展包](https://download.csdn.net/download/weixin_42101164/18409501)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值