题解:AT_abc288_h [ABC288Ex] A Nameless Counting Problem

news/2025/10/12 18:18:38/文章来源:https://www.cnblogs.com/LUlululu1616/p/19136983

用这个题总结一些互异容斥的 trick,参考了周子衡的论文。

题意:求出满足以下两个条件的长度为 \(N\) 的整数序列 \(A = (A_1, A_2, \ldots, A_N)\) 的个数,并对 \(998244353\) 取模。

  • \(0 \leq A_1 \leq A_2 \leq \cdots \leq A_N \leq M\)
  • \(A_1 \oplus A_2 \oplus \cdots \oplus A_N = X\)

做法:

首先考虑,如果有偶数次出现的数我们直接给他消掉,这样的好处是我们可以不再考虑等于号,也就可以直接考虑无序的方案数除以一个阶乘就可以了,比较方便。

\(f_n\) 代表 \(n\) 个数互异,且每个数 \(\le M\),异或值为 \(X\) 的方案数,那么答案是:

\[\sum_{i=0}^{[\frac{n}{2}]}\frac{f_{n-2i}}{(n-2i)!}\binom{M+i}{i} \]

解释一下,这里是枚举我有 \(2i\) 个数出现次数是偶数,两个两个一组,那么就等于我要在 \(M+1\) 个权里扔 \(i\) 个球,稍微化简就是后面的组合数。

然后考虑 \(f\) 怎么求,注意这里有一个互异的限制,我们考虑用互异容斥解决,我们借这个题来介绍一下这个 trick。

互异难做,我们考虑枚举若干个集合,即枚举一个全集的划分 \(\mathcal{P}\),然后再乘上一个容斥系数,使得最后我们得到的是必须互异。

不妨认为我们在相同的元素间连一条边,那么我们的目标是图中边为空。

那么假设 \(F,G\) 分别为 \(F_n=\sum\limits_{E\in E_n, c(E)=1}(-1)^{|E|},G_n=\sum\limits_{E\in E_n} (-1)^{|E|}\),这里 \(E_n\)\(n\) 阶完全图的边集,我们可以容斥算出来 \(F\)

\[F_n=G_n-\sum_{i=1}^n\binom{n-1}{i-1}G_iF_{n-i} \]

解释一下,我们考虑如果有多于一个连通块,那么我们就枚举 \(1\) 所以在的连通块然后再算剩余的贡献,跟联通无向图计数有点像,只不过我们这里是 \(-1\) 为底数而不是 \(2\)

注意到 \(G\) 只有第 \(0,1\) 项值为 \(1\),其他都是 \(0\),带到柿子里可以解得 \(F_n=(-1)^{n-1}(n-1)!\)

那么回到原题,我们枚举连通块大小,然后乘上这个 \(F\),再乘上连通块贡献即可。考虑连通块的贡献,如果连通块大小是偶数,那么就意味着他们异或和一定为 \(0\),有 \((m+1)\) 种方案,否则若干个奇数大小的块需要异或起来等于 \(X\),这个我们后面再计算。

所以我们现在关心的只有所有连通块总大小和有多少个奇连通块,设 \(coef_{i,j}\) 代表目前有 \(i\) 个点和 \(j\) 个奇连通块,有转移式:

\[coef_{i,j}=\sum_{k=1}^i\binom{i-1}{k-1}F_kcoef_{i-k,j-k\bmod 2}([k\bmod 2=0]M+1) \]

然后计算 \(f\) 就直接枚举有多少个奇连通块,有转移式:

\[f_i=\sum_{j=1}^i coef_{i,j}\operatorname{val}(j) \]

这里 \(\operatorname{val}(n)\) 代表我用 \(n\) 个数,可以相同,异或和为 \(X\) 的方案数,这个可以用 dp 计算。具体的,记 \(dp_{i,j,k}\) 代表我考虑到了第 \(i\) 位,有 \(j\) 个数需要考虑 \(M\) 的限制,\(k\) 的数不需要考虑,转移直接枚举两类数分别有多少个数选 \(0/1\) 即可。

时间复杂度 \(O(n^3\log m)\)

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 205, mod = 998244353;
int dp[32][maxn][maxn], vis[32][maxn][maxn], m, n, X, C[maxn][maxn];
int cal(int d, int x, int y) {if(d == -1)return 1;if(vis[d][x][y])return dp[d][x][y];vis[d][x][y] = 1;if(!((m >> d) & 1)) {for (int i = ((X >> d) & 1); i <= y; i += 2)dp[d][x][y] = (dp[d][x][y] + C[y][i]) % mod;dp[d][x][y] = dp[d][x][y] * cal(d - 1, x, y) % mod;return dp[d][x][y];}int res[2] = {0, 0}, val[2] = {0, 0}, t = ((X >> d) & 1);for (int i = 0; i <= y; i++)res[i & 1] = (res[i & 1] + C[y][i]) % mod;for (int i = 0; i <= x; i++)val[(x - i) & 1] = (val[(x - i) & 1] + cal(d - 1, x - i, y + i) * C[x][i] % mod) % mod;dp[d][x][y] = (res[0] * val[(X >> d) & 1] % mod + res[1] * val[1 ^ ((X >> d) & 1)] % mod) % mod;
//	if(dp[d][x][y])
//		cout << d << " " << x << " " << y << " " << dp[d][x][y] << endl;return dp[d][x][y];
}
int coef[maxn][maxn], g[maxn], val[maxn], revjc[maxn];
int qpow(int x, int k, int p) {int res = 1;while(k) {if(k & 1)res = res * x % p;x = x * x % p, k >>= 1;}return res;
}
signed main() {
//	freopen("test.in", "r", stdin);
//	freopen("std.out", "w", stdout);cin >> n >> m >> X;C[0][0] = 1;for (int i = 1; i <= n; i++) {C[i][0] = 1;for (int j = 1; j <= i; j++)C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % mod;}revjc[0] = revjc[1] = 1;for (int i = 2; i <= n; i++)	revjc[i] = (mod - mod / i) * revjc[mod % i] % mod;for (int i = 2; i <= n; i++)revjc[i] = revjc[i - 1] * revjc[i] % mod;val[0] = 1;for (int i = 1; i <= n; i++)val[i] = mod - val[i - 1] * i % mod;coef[0][0] = 1;for (int i = 1; i <= n; i++) {for (int t = 0; t <= i; t++) {for (int j = 1; j <= i; j++) {if(t - (j & 1) >= 0)coef[i][t] = (coef[i][t] + coef[i - j][t - (j & 1)] * C[i - 1][j - 1] % mod * val[j - 1] % mod * ((j & 1) ? 1 : (m % mod + 1))) % mod;//		cout << i << "  " << t << " " << j << " " << coef[i][t] << endl;}}}for (int i = 0; i <= n; i++) {for (int j = 0; j <= i; j++)g[i] = (g[i] + coef[i][j] * cal(31, j, 0)) % mod;}int comb = 1;int ans = 0;for (int i = 0; i <= n / 2; i++) {ans = (ans + g[n - 2 * i] * revjc[n - 2 * i] % mod * comb) % mod;comb = comb * qpow((i + 1), mod - 2, mod) % mod * (m % mod + i + 1) % mod;}cout << ans << endl;return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/935574.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025 年 CBN 砂轮源头厂家最新推荐榜单:专业实力与客户满意度全景解析及选购指南

在航空航天零部件精密切削、电子芯片超精密研磨、汽车发动机关键部件加工等高端制造领域,CBN 砂轮作为核心耗材,其品质直接决定加工精度与生产效率。然而当前市场乱象频发:部分厂家技术薄弱,产品耐用性与精度稳定性…

JDK安装和卸载

新的快捷键 常用 shift+delete:永久删除文件 ctrl+shift+esc:打开任务管理器 alt+f4:关闭进程 ps:前阵子ow流行发一些图片表情和不同颜色字体的时候,很多人用来伪装系统提示引诱玩家按下alt+f4,结果真有人不知道…

Python定义一个User类的基本写法

定义一个类的基础语法如下: class User:# 初始化方法或者叫构造器def __init__(self, name, email):self.name = name # 实例变量name定义和赋值self.email = email # 实例变量email定义和赋值# 一个实例方法def gr…

Python飞快入门专业版(四十八):Python面向对象之多态:不同对象调用同一办法的不同达成(实战案例)

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

10.12 CSP-S模拟30 改题记录

10.12 啥也不会场HZOJ 写在前面 貌似T3T4不太可改,遂先把前两题的写了。大概就是T1打表3小时没找到规律吧,喜提0pts。真是成也T1,败也T1。Dearest Darling My universe 亲爱的 亲爱的宇宙啊 날 데려가 줄래 能否带我…

ubuntu源码编译指定版本make

在Ubuntu系统中,源码编译是安装软件的一种高级方法,它允许用户针对特定的系统环境进行优化和定制。下面是一个针对Ubuntu平台从源码编译特定版本软件的详细流程,步骤旨在面向有一定Linux操作经验的用户。 准备工作安…

【LeetCode】274. H 指数

274. H 指数 题目 给你一个整数数组 citations ,其中 citations[i] 表示研究者的第 i 篇论文被引用的次数。计算并返回该研究者的 h 指数。 根据维基百科上 h 指数的定义:h 代表“高引用次数” ,一名科研人员的 h 指…

python之多态

多态 类具有继承关系,并且子类类型可以向上转型看做父类类型,如果我们从 Person 派生出 Student和Teacher ,并都写了一个 whoAmI() 方法:class Person(object):def __init__(self, name, gender):self.name = name…

Ubuntu系统部署Anaconda环境及Python语言的详细流程

Anaconda是一个流行的Python数据科学及机器学习平台,它聚集了许多用于科学计算、数据分析和机器学习的库。在Ubuntu系统中部署Anaconda环境涉及到下载、安装、设置环境变量以及使用conda创建和管理虚拟环境等几个步骤…

python之继承

继承特性,面向对象的三大特征之一。通过继承从其它类获取属性和方法 继承特性 # 一个类中有方法重复,但又不能实现全部功能 # 通过定义class 类名(父类):继承父类的所有属性和方法 class People:def __init__(self,n…

RK3568+MCU实时机器人解决方案 - 教程

RK3568+MCU实时机器人解决方案 - 教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Mona…

做题记录 #2

A. ABC427G Takahashis Expectation 2 (6.5) 非常厉害的题目。 首先肯定考虑维护一个答案函数,初始为 \(y=x\),那么每次操作相当于用一条横线砍它,上面 -b 下面 +a。 考场上想了一个正确性其实不是很显然,感觉也不…

力扣 第455场周赛(A~D)

力扣 第455场周赛(A~D)$(".postTitle2").removeClass("postTitle2").addClass("singleposttitle");A:出现次数能被 K 整除的元素总和 签到题,给一个整数数组nums和一个数k,计算nums…

深度学习开源书籍的技术解析

本文介绍了一本结合数学理论与编程实践的深度学习开源书籍,涵盖PyTorch和Tensor框架实现,通过Jupyter Notebook提供交互式学习体验,被多所高校采用为教材。深度学习著作的技术特色 《Dive into Deep Learning》是一…

c++自制游戏盒子

include<bits/stdc++.h> include <windows.h> include <stdio.h> include<conio.h> include<time.h> using namespace std; int x = 0; int* X = &x; char Void[10000] = "\0&…

向量库面试题

什么是向量数据库,和传统数据库相比有什么不同? “向量数据库是一类专门用于存储和检索高维向量数据的数据库。向量通常是从文本、图像、音频等非结构化数据通过 embedding 模型生成的高维浮点数组。 与传统数据库相…

02 常用快捷键和指令

新的快捷键 常用 shift+delete:永久删除文件 ctrl+shift+esc:打开任务管理器 alt+f4:关闭进程 ps:前阵子ow流行发一些图片表情和不同颜色字体的时候,很多人用来伪装系统提示引诱玩家按下alt+f4,结果真有人不知道…

深圳公共资源交易中心 www.szzfcg.cn

各市场主体: 感谢您长期以来的关心和支持!深圳交易集团有限公司(深圳公共资源交易中心)政府采购业务分公司网站进行了全新升级,网站栏目设计及功能布局较以往得到了进一步提升,将更好地为市场主体提供交易服务和…

mysql百分数转小数点格式

基本转换方法 假设我们有一个包含百分数值的MySQL表,这些百分数值以字符串的形式存储,例如 50%。我们的目标是将这些百分数值转换为小数点格式,即 0.50。 转换的基本方法是将百分数值除以100。在MySQL中,可以通过简…

如何下载Sora视频 - 2025完整指南

如何下载Sora视频 - 2025完整指南学习如何使用我们的网站或Chrome扩展程序下载Sora AI视频。本综合指南提供了两种不同方法下载Sora视频的分步说明,为最佳用户体验进行了优化。学习如何使用我们的网站或Chrome扩展程序…