首页 > 其他分享 >[ABC327G] Many Good Tuple Problems 题解

[ABC327G] Many Good Tuple Problems 题解

时间:2024-02-08 09:55:35浏览次数:20  
标签:二分 kMod ABC327G Good 个点 int 题解 kMaxM 条边

Description

对于一对长度均为 \(M\) 且元素值在 \(\left[1, N\right]\) 之间的序列 \((S, T)\),定义其为好的当且仅当:

  • 存在一个长度为 \(N\) 的 \(01\) 序列 \(X\),使得其满足如下条件:

    • 对于任意 \(i \in \left[1, M\right]\),有 \(X_{S_i} \neq X_{T_i}\)。

给定 \(N, M\),求在所有可能的 \(N^{2M}\) 种长度均为 \(M\) 且元素值在 \(\left[1, N\right]\) 之间的序列对 \((A, B)\) 中,有多少对序列是好的。

对 \(998244353\) 取模。

\(1 \le N \le 30, 1 \le M \le 10^9\)。

Solution

首先对于两个序列他们合法的条件就是把所有 \(S_i\) 和 \(T_i\) 连边后是个二分图,于是原题就等价于要求有多少个 \(n\) 个点 \(m\) 条边的有标号二分图。

先考虑如何求出 \(n\) 个点 \(m\) 条边的简单有标号二分图数量。然后会发现不好把染色方式的影响去掉,所以先不考虑染色方式的影响去做。

设 \(f_{n,m}\) 表示 \(n\) 个点 \(m\) 条边的简单二分图数(染色方式不同算不同的方式),那么可以得到:

\[f_{n,m}=\sum_{i=0}^{n}{\binom{n}{i}\binom{i(n-i)}{m}} \]

但是这个状态无法把连通块个数表示出来,而无法去除染色方式的影响,所以可以考虑求出 \(n\) 个点 \(m\) 条边的简单连通二分图数(染色方式不同算不同的方式),这样只要把方案数除以 \(2\) 就能去掉连通图染色方式的影响,最后把再把连通图重组成普通简单二分图即可求出答案。

那么设 \(g_{n,m}\) 表示 \(n\) 个点 \(m\) 条边的简单连通二分图数(染色方式不同算不同的方式),可以得到:

\[g_{n,m}=f_{n,m}-\sum_{i=1}^{n-1}\sum_{j=0}^{m}{\binom{n-1}{i-1}\times g_{i,j}\times h_{n-i,m-j}} \]

这个式子就是用总方案减去有至少两个连通块的方案数。

然后设 \(h_{n,m}\) 表示 \(n\) 个点 \(m\) 条边的简单二分图数(染色方式不同算相同的方式),可以得到:

\[h_{n,m}=\frac{\sum_{i=1}^{n}\sum_{j=0}^{m}{\binom{n-1}{i-1}\times g_{i,j}\times h_{n-i,m-i}}}{2} \]


最后考虑怎么处理有重边的情况,先设有 \(k\) 种边。

题目转化为有一个长度为 \(m\) 的序列,序列每个数的取值范围为 \([1,k]\),问有多少个序列满足他们 \(k\) 种数都出现过。容易发现直接容斥即可。

时间复杂度:\(O(n^6+n^4\log m)\)。

Code

#include <bits/stdc++.h>

// #define int int64_t

const int kMaxN = 35, kMaxM = 505, kMod = 998244353, kInv2 = 499122177;

int n, m;
int C[kMaxM][kMaxM], pw[kMaxM], f[kMaxN][kMaxM], g[kMaxN][kMaxM], h[kMaxN][kMaxM];

int add(int x, int y) { return (x + y) >= kMod ? (x + y - kMod) : (x + y); }
int sub(int x, int y) { return (x - y) < 0 ? (x - y + kMod) : (x - y); }
void inc(int &x, int y) { (x += y) >= kMod ? (x -= kMod) : x; }
void dec(int &x, int y) { (x -= y) < 0 ? (x += kMod) : x; }

int qpow(int bs, int idx = kMod - 2) {
  int ret = 1;
  for (; idx; idx >>= 1, bs = 1ll * bs * bs % kMod)
    if (idx & 1)
      ret = 1ll * ret * bs % kMod;
  return ret;
}

void prework() {
  C[0][0] = 1;
  for (int i = 1; i <= 500; ++i) {
    C[i][0] = 1;
    for (int j = 1; j <= i; ++j)
      C[i][j] = add(C[i - 1][j], C[i - 1][j - 1]);
  }
}

void dickdreamer() {
  std::cin >> n >> m;
  prework();
  f[0][0] = 1;
  for (int i = 1; i <= n; ++i) {
    for (int j = 0; j <= i * (i - 1) / 2; ++j) {
      for (int k = 0; k <= i; ++k) {
        inc(f[i][j], 1ll * C[i][k] * C[k * (i - k)][j] % kMod);
      }
    }
  }
  g[0][0] = 1;
  for (int i = 1; i <= n; ++i) {
    for (int j = 0; j <= i * i / 4; ++j) {
      g[i][j] = f[i][j];
      for (int k = 1; k < i; ++k) {
        for (int s = 0; s <= std::min(k * k / 4, j); ++s) {
          dec(g[i][j], 1ll * C[i - 1][k - 1] * g[k][s] % kMod * f[i - k][j - s] % kMod);
        }
      }
      // std::cerr << i << ' ' << j << ' ' << g[i][j] << '\n';
    }
  }
  h[0][0] = 1;
  for (int i = 1; i <= n; ++i) {
    for (int j = 0; j <= i * i / 4; ++j) {
      for (int k = 1; k <= i; ++k) {
        for (int s = 0; s <= std::min(k * k / 4, j); ++s) {
          inc(h[i][j], 1ll * C[i - 1][k - 1] * g[k][s] % kMod * h[i - k][j - s] % kMod * kInv2 % kMod);
        }
      }
      // std::cerr << i << ' ' << j << ' ' << h[i][j] << '\n';
    }
  }
  int ans = 0;
  for (int i = 0; i <= std::min(n * (n - 1) / 2, m); ++i) {
    int w = 0;
    for (int j = 0; j <= i; ++j) {
      inc(w, 1ll * (((i - j) & 1) ? (kMod - 1) : 1) * C[i][j] % kMod * qpow(j, m) % kMod);
    }
    inc(ans, 1ll * w * h[n][i] % kMod);
    // std::cerr << w << ' ' << h[n][i] << '\n';
  }
  std::cout << 1ll * ans * qpow(2, m) % kMod << '\n';
}

int32_t main() {
#ifdef ORZXKR
  freopen("in.txt", "r", stdin);
  freopen("out.txt", "w", stdout);
#endif
  std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0);
  int T = 1;
  // std::cin >> T;
  while (T--) dickdreamer();
  // std::cerr << 1.0 * clock() / CLOCKS_PER_SEC << "s\n";
  return 0;
}

标签:二分,kMod,ABC327G,Good,个点,int,题解,kMaxM,条边
From: https://www.cnblogs.com/Scarab/p/18011598

相关文章

  • CF1918G Permutation of Given 题解
    总体思路本题通过每次在已知序列中加入\(2\)个元素的方法,可以构造出满足条件的序列\(A\),这里提供一种新的构造方法。性质因为序列\(A\)中所有元素构成的可重集与序列\(B\)中所有元素构成的可重集完全相等,所以\(A\)中所有元素之和与\(B\)中所有元素之和相等。\[\s......
  • SP277 CTGAME - City Game 题解
    题目传送门前置知识单调栈解法令\(f_{i,j}(1\lei\len,1\lej\lem)\)表示从\((1,j)\)到\((i,j)\)中以\((i,j)\)结尾的均为F的子串长度,即\((i,j)\)上面可延伸的最大距离(子矩形的长)。用单调栈的第一维存储子矩形的长,第二维存储子矩形的宽。考虑依次枚举每一......
  • qoj8171 Cola 题解
    题目链接点击打开链接题目解法很牛的题!!!会不了一点令\(pref_i\)表示第\(i\)轮知道了前缀\([1,...,i]\)考虑怎样的\(pref\)序列是合法的(即采用最优策略):\(pref_0=0\)\(\forall_{i\in[0,n-1]}\;pref_i\lepref_{i+1}\)\(pref\)中\(x\)的出现次数\(\len-x-1\),因......
  • [AGC021E] Ball Eat Chameleons 题解
    Description有\(n\)只变色龙,一开始都是蓝色。现在你喂了\(k\)次球,每次指定一只变色龙吃下你指定颜色的球。一只变色龙从蓝色变成红色当且仅当它吃的红球比蓝球多;一只变色龙从红色变成蓝色当且仅当它吃的蓝球比红球多。求最后能使所有变色龙都变成红色的方案数。两个方案......
  • AT_abc270_g [ABC270G] Sequence in mod P 题解
    题目传送门前置知识大步小步算法解法递推式为\(x_{n}=(ax_{n-1}+b)\bmodp\),发现可以统一消去\(\bmodp\),只在最后参与计算。以下过程省去模运算。当\(x_{0}=t\)时,则\(n=0\)即为所求。当\(a=0,x_{0}\net\)时,递推式转化为\(x_{n}=b\bmodp\)。若\(b=t\),则......
  • UVA10225 Discrete Logging 题解
    题目传送门前置知识大步小步算法题意多组询问,每次询问依次给定\(p,a,b\),求\(a^{x}\equivb\pmod{p}\)的最小非负整数解,其中\(a,p\)互质。解法BSGS板子题,不做过多介绍。貌似本题比P3846[TJOI2007]可爱的质数/【模板】BSGS和BZOJ3239DiscreteLogging数据较强......
  • [AGC041F] Histogram Rooks 题解
    题目链接点击打开链接题目解法好牛(难)的题!!!所有都被覆盖不难想到容斥暴力的容斥是钦定集合\(S\)中的位置都没被覆盖,然后把不能填棋子的点都去掉,假设剩下的不受限制的点的个数为\(c\),则答案为\(\sum2^c(-1)^{|S|}\)这个暴力是很难直接优化的如果一列被有点被钦定了,那么......
  • 【洛谷 P2670】[NOIP2015 普及组] 扫雷游戏 题解(模拟)
    [NOIP2015普及组]扫雷游戏题目背景NOIP2015普及组T2题目描述扫雷游戏是一款十分经典的单机小游戏。在行列的雷区中有一些格子含有地雷(称之为地雷格),其他格子不含地雷(称之为非地雷格)。玩家翻开一个非地雷格时,该格将会出现一个数字——提示周围格子中有多少个是地雷格。游戏的......
  • UVA12024 Hats 题解
    题目传送门前置知识错位排列题意有\(t\)组询问,每次询问给定一个\(n\),表示有\(n\)个人,每人各有一个属于自己的帽子,求所有人都带错帽子的概率(不要求约分至最简形式)。解法错排板子题,\(\dfrac{D_{n}}{A_{n}^{n}}\)即为所求。代码#include<bits/stdc++.h>usingnamespac......
  • CF231E 题解
    本文采用CCBY-NC-SA4.0协议发布。前言提供一个圆方树做法。孩子圆方树学傻了,忘了还有缩点这回事。正文建圆方树。考虑一条圆方树上的路径,哪些点对答案有贡献:方点,这表示路径经过一个环,方案数\(\times2\).旁边有方点的圆点。这表示走到这时可以选择在环上绕一圈,方......