[ARC163D] Sum of SCC 题解

感觉纯结论题。

思路#

首先有一个很重要的结论:

竞赛图强连通缩点后的 DAG 呈链状,前面的所有点向后面的所有点连边。

如果用强连通分量的角度来看是这样的:

一个竞赛图的 SCC 个数等于将其点集划分为两个集合 A,B(可为空集)并满足以下限制的方案数 1

对于每条满足 uA,vb 的边 (u,v),都满足其方向为 uv

证明其实也很简单,利用归纳法逐一加入每个 SCC 即可。

但感觉很难在不知道的情况下想到。

知道了以后这个题就很简单。

直接 dp 即可。

时间复杂度:O(n5)

Code#

#include <bits/stdc++.h>
using namespace std;

const int mod = 998244353;

int n, m, k;
int f[35][35][450];
int g[35][35][450];
int c[450][450];

inline void add(int &x, int y) {
  if ((x += y) >= mod) x -= mod;
}

int main() {
  cin >> n >> m, k = n * (n - 1) / 2;
  f[0][0][0] = 1;
  for (int i = 0; i <= k; i++) c[i][0] = 1;
  for (int i = 1; i <= k; i++)
    for (int j = 1; j <= k; j++)
      if ((c[i][j] = c[i - 1][j] + c[i - 1][j - 1]) >= mod) c[i][j] -= mod;
  for (int i = 1; i <= n; i++) {
    memset(g, 0, sizeof g);
    for (int l = 0; l < i; l++) {
      for (int r = 0; l + r < i; r++) {
        for (int j = 0; j <= l * r; j++) {
          add(g[l + 1][r][j], f[l][r][j]);
          add(g[l][r + 1][j + l], f[l][r][j]);
        }
      }
    }
    memcpy(f, g, sizeof f);
  }
  int ns = 0;
  for (int l = 0; l <= n; l++) {
    for (int r = 0; l + r <= n; r++) {
      for (int j = 0; j <= l * r; j++) {
        if (j <= m) ns = (ns + 1ll * c[l * (l - 1) / 2 + r * (r - 1) / 2][m - j] * g[l][r][j]) % mod;
      }
    }
  }
  cout << (ns - c[n * (n - 1) / 2][m] + mod) % mod << "\n";
}

作者:JiaY19

出处:https://www.cnblogs.com/JiaY19/p/18698567

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   JiaY19  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)
more_horiz
keyboard_arrow_up light_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示