CF1657E Star MST

Problem

有一个 n 个点的无向完全图,边权 e[1,m] ,已知该图的最小生成树的权值与所有与 1 号点相连的边的边权和相同,求有多少种构图方式,答案对 998244353 取模。

2n250,1m250

Input

一行两个整数 nk

Output

一行一个整数表示答案。

Sample

Input 1

3 2

Output 1

5

Input 2

4 4

Output 2

571

Input 3

6 9

Output 3

310640163

Input 4

42 13

Output 4

136246935

Solution

比较难想的DP题。

考虑定义 fi,j 表示当前给与 1 相连的 j 条边分配了权值,每条边权值在 [1,i] 之间的方案数。

由题意可以得到,对于一条边 (x,y),若 x1y1,则该边的权值 Wx,yW1,xWx,yW1,y

nk 都很小,可以考虑两层循环枚举状态,一层循环进行转移。

假设我们已知为 fi1,j 的答案,从剩下的 n1j 条边中选出 k 条边赋值为 i,容易可以得到转移:

fi,j+k=fi,j+k+fi1,jcnj1,kPow(mi+1,jk+k(k1)/2)

其中 cnj1,k 为从 nj1 条边中选出 k 条边的方案数。(组合数)

加入的这 k 条边之间连出的 k(k1)/2 条边以及这 k 条边与前面 j 条边之间连出的 j×k 条边的权值都必须在 [i,m] 之间,每一条边都有 mi+1 种选择,还需乘上这部分的贡献。

最后 fm,n1 即为答案,权值不超过 i,分配了 n1 条边。

代码:

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

const int kmax = 255;
const int Mod = 998244353;

int n, m;
long long c[kmax][kmax];
long long f[kmax][kmax];

long long Pow(long long x, long long y) {
  long long r = 1;
  for (; y; y >>= 1) {
    if (y & 1) r = r * x % Mod;
    x = x * x % Mod;
  }
  return r;
}

void Init() { // 预处理组合数
  c[0][0] = 1;
  for (int i = 1; i < kmax; i++) {
    c[i][0] = 1;
    for (int j = 1; j <= i; j++) {
      c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % Mod;
    }
  }
}

int main() {
  Init();
  cin >> n >> m;
  f[0][0] = 1;
  for (int i = 1; i <= m; i++) {
    for (int j = 0; j < n; j++) {
      for (int k = 0; k < n - j; k++) {
        f[i][j + k] = (f[i][j + k] + f[i - 1][j] * c[n - j - 1][k] % Mod * Pow(m - i + 1, j * k + k * (k - 1) / 2) % Mod) % Mod; // 直接转移,记得取模
      }
    }
  }
  cout << f[m][n - 1];
  return 0;
}
posted @   ereoth  阅读(18)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示