当前位置: 首页 > news >正文

洛谷 P3214 [HNOI2011] 卡农


题目传送门


前言

再次败在 d p dp dp 手下,但是数据范围这么小应该是可以看出是 d p dp dp 的(毕竟对于其他组合数的问题数据范围都是 1 0 9 10^9 109 起步)。


思路

题意简化

现有 1 , 2 , 3 , . . . , n − 1 , n 1, 2, 3, ... , n - 1, n 1,2,3,...,n1,n,从其所组成的 2 n − 1 2^n - 1 2n1 个非空集合中选出 m m m 个,每个集合只能选一次,求【使 ∀ i ∈ [ 1 , n ] \forall i \in [1, n] i[1,n] 在所选集合中,出现次数均为偶数的】的选择方案书,答案对 1 0 8 + 7 10^8 + 7 108+7 取模。

明确两点:

  1. 出现 0 0 0 次也算出现偶数次;
  2. 一个集合中,不可能出现两个相同的数(集合的互斥性)。

状态设计

d p i dp_i dpi 表示选了 i i i 个集合的合法方案数。
注意:在之后的转移使,我们先 只需要让这 i i i 个集合 满足“每个数出现次数为偶数”的限制。

状态转移

限制 1 1 1:每个数只能出现偶数次

首先看起来题目所给的“每个数出现偶数次”的限制不太好弄,所以我们先考虑假如已经有 i − 1 i - 1 i1 个确定的集合,可以怎么添加一个集合,使得这 i i i 个集合满足这条限制。

对于一个数 x x x

  1. 假如它在前 i − 1 i - 1 i1 个集合中出现了奇数次,那么它一定要在最后一个集合在出现一次,这样才能保证 x x x i i i 个集合中总共出现了偶数次;
  2. 假如它在前 i − 1 i - 1 i1 个集合中出现了偶数次,那么它就不可能出现在最后一个集合中,因为为了维持其出现偶数次,且每个集合不能出现相同的数,所以在最后一个集合中,其出现次数只能为 0 0 0

由上述看题解分析,假如已经确定了 i − 1 i - 1 i1 个集合,那最后一个集合就是确定的。

先不管其他限制,就但从这条限制来看,它就有 A 2 n − 1 i − 1 A_{2^n - 1}^{i - 1} A2n1i1 种可能(这里之所以是排列不是组合,是因为题目让我们求出的【所选集合方案是不顾选出集合顺序的】,所以我们在最后让答案乘以 m ! m! m! 的逆元就好了)。

限制 2 2 2:集合不能为空集

由于可能在前 i − 1 i - 1 i1 个集合中,每一个数都出现了偶数次,所以在最后一个集合中任何数都不能出现,即最后一个集合使空集,这样是不合法的。

我们从容斥角度考虑转移,看看最后一个集合为空集的有多少种可能。

把最后一个空集去除后,发现剩下的 i − 1 i - 1 i1 个集合正好是一个满足【取 i − 1 i - 1 i1 个集合使其满足 “每个数只能出现偶数次” 限制】的取集合方案(因为若最后一个集合为空集,那么前 i − 1 i - 1 i1 个集合就必定满足 “每个数出现偶数次” 限制),这样的情况有 d p i − 1 dp_{i - 1} dpi1 种。

所以在总的选择方案中减去 d p i − 1 dp_{i - 1} dpi1 就行。

限制 3 3 3:每个集合只能选一次,即不能出现两个相同的集合

由于前 i − 1 i - 1 i1 个集合一定互不相同(因为我们是从 n n n 个数组成的 2 n − 1 2^n - 1 2n1 个互不相同的集合中选出的),所以只考虑【第 i i i 个集合与前 i − 1 i - 1 i1 个集合中】有一个相同的方案。

先明确一点:假如 i i i 与前 i − 1 i - 1 i1 个集合中的某个相同(假设是第 j j j 个集合),那么决定第 i i i 个集合构造方法的就是集合 j j j

因此,我们如果去除集合 i , j i, j i,j,那么剩下的 i − 2 i - 2 i2 个集合一定能形成一组满足【取 i − 2 i - 2 i2 个集合使其满足 “每个数只能出现偶数次” 限制】的取集合方案。因为两个集合中的数相同,因此删除这两个集合的话,集合中的数也是成对被删除的,因此能构成。这样的 i − 2 i - 2 i2 个集合共有 d p i − 2 dp_{i - 2} dpi2 种。

又因为 j j j i − 1 i - 1 i1 种取法,集合 i i i 2 n − 1 − ( i − 2 ) 2^n - 1 - (i - 2) 2n1(i2) 种(即在所有的 2 n − 1 2^n - 1 2n1 个集合中,去除【已有的 i − 2 i - 2 i2 个集合】剩下的之中,再选一个),剩下的 i − 2 i - 2 i2 个集合共有 d p i − 2 dp_{i - 2} dpi2 种,所以这个非法方案数是 ( i − 1 ) × ( 2 n − 1 − ( i − 2 ) ) × d p i − 2 (i - 1) \times (2^n - 1 - (i - 2)) \times dp_{i - 2} (i1)×(2n1(i2))×dpi2

综上,转移方程就是:
d p i = A 2 n − 1 i − 1 − d p i − 1 − ( i − 1 ) × ( 2 n − 1 − ( i − 2 ) ) × d p i − 2 dp_i = A_{2^n - 1}^{i - 1} - dp_{i - 1} - (i - 1) \times (2^n - 1 - (i - 2)) \times dp_{i - 2} dpi=A2n1i1dpi1(i1)×(2n1(i2))×dpi2

边界条件

首先是 d p 1 = 0 dp_1 = 0 dp1=0:因为只选一个非空的不重集合就让每个数出现偶数次显然是不可能的;
其次是 d p 2 = 0 dp_2 = 0 dp2=0:因为要在前两个集合中,就使每个数出现偶数次,要么得是两个空集,要么两个集合就得一样,这样显然也是不合法的。

答案

d p m × i n v ( m ! ) dp_m \times inv(m!) dpm×inv(m!),因为题目要求出的集合是不顾 m m m 个集合顺序的,而在计算时我们有考虑了其顺序,所以要除去 m ! m! m!

复杂度

时间空间均为 O ( m ) O(m) O(m)


代码

#include <bits/stdc++.h>

#define int long long

using namespace std;

const int maxn = 1e6 + 7;
const int mod  = 1e8 + 7;

int n, m;
int facm = 1, invm;
int tot;
int qpow(int x, int y) {
	int res = 1;
	for (; y; y >>= 1, x = x * x % mod)
		if (y & 1) res = res * x % mod;
	return res;
}

int dp[maxn], A[maxn];
signed main() {
	scanf("%lld%lld", &n, &m);
	for (int i = 1; i <= m; ++i)
		facm = facm * i % mod;
	invm = qpow(facm, mod - 2);
	tot = (qpow(2, n) - 1 + mod) % mod;
	A[0] = 1;
	for (int i = 1; i <= m; ++i)
		A[i] = A[i - 1] * (tot - i + 1) % mod;
	dp[1] = dp[2] = 0;
	for (int i = 3; i <= m; ++i)
		dp[i] = ((A[i - 1] - dp[i - 1] - 
				 (tot - i + 2) * (i - 1) % mod * dp[i - 2] % mod) % mod + mod) % mod;
	printf("%lld\n", dp[m] * invm % mod);
	return 0;
}
http://www.dtcms.com/a/113333.html

相关文章:

  • 2.IO流的体系和字节输出流FileOutputStream的基本用法
  • macos 魔搭 模型下载 Wan-AI ComfyUI
  • L2-024 部落 #GPLT,并查集 C++
  • 智能驾驶中预测模块简介
  • 广州t11基地顺利完成交割,TCL华星技术产能双升级
  • 【java】Class.newInstance()
  • 硬币找零问题
  • 特征值与特征向量:从理论到应用的全面解析
  • Java类加载问题
  • STM32单片机入门学习——第16节: [6-4] PWM驱动LED呼吸灯PWM驱动舵机PWM驱动直流电机
  • 《AI大模型应知应会100篇》第4篇:Transformer架构深入浅出:大模型的基石
  • cadence17.4和16.6同时安装无法使用的问题
  • 关于图片分类任务的猜想 | 撰写论文 paper
  • .net多贸易公司借入借出归还设备进销存管理系统软件租金计算库存管理
  • M芯片,能运行普通应用程序的原架构虚拟机
  • Java的Selenium元素定位-xpath
  • LeetCode热题100记录-【二叉树】
  • 【Deep Reinforcement Learning Hands-On Third Edition】【第1章:什么是强化学习】
  • 《海空重力测量理论方法及应用》之一重力仪系统组成及工作原理(下)
  • qt designer 软件主题程序设计
  • Python精进系列:从 __name__ 开始了解 python 常见内置变量
  • synchronized 锁升级机制详解
  • ROS2 多机时间同步(Chrony配置简明指南)
  • docker本地部署anythingllm
  • C++重载运算符的本质
  • 将 DataFrame 中某一列的列表拆分成多个独立的列的方式
  • Linux上位机开发实践(做一专多能的方案提供者)
  • 从情感分析到朴素贝叶斯法:基于朴素贝叶斯的情感分析如何让DeepSeek赋能你的工作?
  • 【Kubernetes】RBAC(基于角色的访问控制)如何设置?如何管理 Kubernetes 的权限?
  • MCP 极简入门 - 三分钟 Cline + Smithery 运行 time 服务