卡农 -- \(HNOI2011\)

$$luogu$$

$$HZOI$$


题意

给定一个 集合 $ A= { 1 \le x \le n | x } $ , 求出其 \(m\) 个不相同的且不为空集的子集,使得第 \(i\) 个元素的在所有选出的子集中出现的次数 \(appear_i \mod 2 = 0\)


题解

首先一个已知结论:

对于一个 \(A\) 这样的集合,他不同的子集个数为 \(2^n\)

那么这时我们减去空集,那么可选的为 \(2^n - 1\) 种。

你影响你最后的每个元素的出现次数的是第 \(m\) 次的选择。

若第 \(i\) 个数在前 \(m - 1\) 个子集中出现的次数为奇数,那么 \(i\) 在最后一个中必定出现。

反之就不会出现。

所以 前 \(m - 1\) 个怎么取值都行。

考虑此时 \(ans_m\) 为 \(m\) 个子集满足条件的方案数。

不考虑什么奇偶,前 \(m - 1\) 个能选的总方案数为 :

\[ans_m += C^{ m - 1 }_{2 ^ n - 1}
\]

第一种情况:若 \(1 \dots n\) 在前 \(m - 1\) 个子集中出现的次数均为偶数,则此时末尾为空集,显然不可取,所以:

\[ans_m -= ans_{m - 1}
\]

第二种情况:若所有出现次数为奇数的数构成的集合 \(B\) 已经被选入,则:

\[ans_m -= (2 ^ n - 1 - (m - 2)) \times ans_{m - 2}
\]

解释一下:

那么我们可以看做就是最后一个集合 \(=\) 第 \(m - 1\) 个集合

那前 \(m - 2\) 个肯定是符合要求的。那肯定前 \(m - 2\) 个是不重叠的那这个重叠的集合的取值种数为 $2 ^ n - 1 - (m - 1) $

最后的处理,现在定义 \(n = 2, m = 3\)

那对于这三种选法,会算成三种,但实际是一种

\[\{1\} , \{2\} , \{1 , 2\}
\]
\[\{1\} , \{1 , 2\} , \{2\}
\]
\[\{2\} , \{1 , 2\} , \{1\}
\]

注意对于前面 $ 2 $ 个集合的来说它的选择的顺序是没关系的。算成三种的原因只是因为最后的一个集合的抠出来的值不同。

所以再除以一个 $ m $

所以 \(DP\) 转移方程为:

\[dp_i = C ^ {i - 1} _ {2 ^ n - 1} - dp_{i - 1} - dp_{i - 2} \times ( 2 ^ n - 1 - ( m - 2 ) )
\]

\(code\)

格式化过的

点击查看代码
#include <bits/stdc++.h>
#define int long long
using namespace std ;
const int N = 1e6 + 1 ;
int dp[ N ], C[ N ] ;
const long long mod = 1e8 + 7 ;
namespace Combination {
int nueyong[ N ], sum_neo[ N ] ;
inline void lear_neoyong() {
sum_neo[ 0 ] = sum_neo[ 1 ] = 1 ;
nueyong[ 1 ] = 1 ;
nueyong[ 0 ] = 1 ; // sum[ 0 ] = sum[ 1 ] = 1 ;
for (int i = 2 ; i < N ; ++ i) {
int p = mod ;
int k = p / i ;
nueyong[ i ] = (k * (p - nueyong[ p % i ])) % p ;
sum_neo[ i ] = (nueyong[ i ] * sum_neo[ i - 1 ]) % p ;
// sum[ i ] = ( i * sum[ i - 1 ] ) % p ;
}
}
int Quick_Pow(int alpha, int beta) {
int ans = 1 ; while (beta > 0) {
if (beta & 1)
ans = (ans * alpha) % mod ; beta >>= 1 ;
alpha = (alpha * alpha) % mod ;
} return ans ;
}
} ;
using namespace Combination ;
inline int read() {
int x = 0, f = 1 ;
char c = getchar() ; while (c < '0' || c > '9') {
if (c == '-') {
f = - f ;
} c = getchar() ;
} while (c >= '0' && c <= '9') {
x = x * 10 + c - '0' ;
c = getchar() ;
} return x * f ;
}
int n, m, all_time, koul ;
signed main() {
n = read() ;
m = read() ;
lear_neoyong() ;
all_time = (((Quick_Pow(2, n) - 1) % mod) + mod) % mod ;
C[ 0 ] = 1 ;
int tot = all_time ; for (int i = 1 ; i <= m ; ++ i) {
C[ i ] = (C[ i - 1 ] * ((tot + mod) % mod)) % mod ;
tot -- ;
} dp[ 2 ] = dp[ 1 ] = 0 ; for (int i = 3 ; i <= m ; ++ i) {
int pri = (C[ i - 1 ] * sum_neo[ i - 1 ]) % mod ;
dp[ i ] = ((((pri - dp[ i - 1 ]) - ((dp[ i - 2 ] * ((all_time - i + 2) % mod + mod) % mod) % mod) + mod) %
mod) * nueyong[ i ]) % mod ;
} cout << dp[ m ] ;
}

结尾撒花 \(\color{pink}✿✿ヽ(°▽°)ノ✿\)

卡农 -- HNOI2011 -- DP&组合的更多相关文章

  1. BZOJ.2339.[HNOI2011]卡农(思路 DP 组合 容斥)

    题目链接 \(Description\) 有\(n\)个数,用其中的某些数构成集合,求构造出\(m\)个互不相同且非空的集合(\(m\)个集合无序),并满足每个数总共出现的次数为偶数的方案数. \(S ...

  2. P3214-[HNOI2011]卡农【dp】

    正题 题目链接:https://www.luogu.com.cn/problem/P3214 题目大意 一个由\(1\sim n\)的所有整数构成的集合\(S\),求出它的\(m\)个不同非空子集满足 ...

  3. bzoj2339[HNOI2011]卡农 dp+容斥

    2339: [HNOI2011]卡农 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 842  Solved: 510[Submit][Status][ ...

  4. [HNOI2011]卡农 (数论计数,DP)

    题面 原题面 众所周知卡农是一种复调音乐的写作技法,小余在听卡农音乐时灵感大发,发明了一种新的音乐谱写规则. 他将声音分成 n n n 个音阶,并将音乐分成若干个片段.音乐的每个片段都是由 1 1 1 ...

  5. P3214 [HNOI2011]卡农

    题目 P3214 [HNOI2011]卡农 在被一题容斥\(dp\)完虐之后,打算做一做集合容斥这类的题了 第一次深感HNOI的毒瘤(题做得太少了!!) 做法 求\([1,n]\)组成的集合中选\(m ...

  6. 【BZOJ2339】[HNOI2011]卡农 组合数+容斥

    [BZOJ2339][HNOI2011]卡农 题解:虽然集合具有无序性,但是为了方便,我们先考虑有序的情况,最后将答案除以m!即可. 考虑DP.如果我们已经知道了前m-1个集合,那么第m个集合已经是确 ...

  7. [BZOJ2339][HNOI2011]卡农

    [BZOJ2339][HNOI2011]卡农 试题描述 输入 见"试题描述" 输出 见"试题描述" 输入示例 见"试题描述" 输出示例 见& ...

  8. BZOJ2339[HNOI2011]卡农——递推+组合数

    题目链接: [HNOI2011]卡农 题目要求从$S=\{1,2,3……n\}$中选出$m$个子集满足以下三个条件: 1.不能选空集 2.不能选相同的两个子集 3.每种元素出现次数必须为偶数次 我们考 ...

  9. [HNOI2011]卡农 题解

    题目描述 众所周知卡农是一种复调音乐的写作技法,小余在听卡农音乐时灵感大发,发明了一种新的音乐谱写规则.他将声音分成 n 个音阶,并将音乐分成若干个片段.音乐的每个片段都是由 1 到 n 个音阶构成的 ...

  10. [HNOI2011]卡农

    题目描述 众所周知卡农是一种复调音乐的写作技法,小余在听卡农音乐时灵感大发,发明了一种新的音乐谱写规则.他将声音分成 n 个音阶,并将音乐分成若干个片段.音乐的每个片段都是由 1 到 n 个音阶构成的 ...

随机推荐

  1. Linux 内核:设备驱动模型 学习总结

    背景 其实之前就转载过别人针对Linux的设备驱动模型(Linux Device Driver Model,LDDM)的文章,但是受限于自身的能力,因此花了点时间重新学习了一下. 前人写的文章很好,我 ...

  2. USB OTG有关协议

    想了解USB OTG的工作原理,需要知道三个协议: ADP:Attach Detection Protocol HNP:Host Negotiation Protocol SRP:Session Re ...

  3. uboot load address、entry point、 bootm address以及kernel运行地址的意义及联系

    按各地址起作用的顺序,uboot引导linux内核启动涉及到以下地址: load address: entry point: 这两个地址是mkimage时指定的 bootm address:bootm ...

  4. 为什么说这款99元国产ARM工业平台,具有“划时代”意义

    随着近年来进口处理器涨价不断,大家会发现市面上已很少见到99元的ARM工业核心板出售. 为满足客户对低成本.高性能的需求,创龙科技推出基于全志T113-i国产ARM工业处理器的"划时代&qu ...

  5. throws和try catch的区别

    1.throws是表明方法抛出异常,需要调用者来处理,如果不想处理就一直向外抛,最后会有jvm来处理: 2.try catch 是自己来捕获别人抛出的异常,然后在catch里面去处理: 一般情况下,第 ...

  6. RPC和心跳机制

    hadoop在节点间的内部通讯使用的是RPC,RPC协议把消息翻译成二进制字节流发送到远程节点,远程节点再通过反序列化把二进制流转成原始的信息. namenode与datanode之间的通信,jobt ...

  7. C#多态性学习,虚方法、抽象方法、接口等用法举例

    1. 多态性定义   C#中的多态性是OOP(面向对象编程)的一个基本概念,它允许一个对象在不同情况下表现出不同的行为,以增强代码的可重用性和灵活性.   根据网上的教程,我们得知C#多态性分为两类, ...

  8. Pypi配置API Token

    技术背景 在许久之前写的一篇博客中,我们介绍过使用twine向pypi上传我们自己的开源包的方法.最近发现这个方法已经不再支持了(报错信息如下所示),现在最新版需要使用API Token进行文件上传, ...

  9. 女朋友问我 LB 是谁?

    科普一下 LB(负载均衡)技术 我的编程导航网站:www.code-nav.cn 大家好,我是鱼皮. 周末在家写代码,无意中跟女朋友提了下 LB,还说 LB 好的呱呱叫. 她笑了笑,问我 LB 是谁? ...

  10. Stopwatch 类来测量时间间隔

    使用 Stopwatch 类来测量时间间隔. 以下是一个示例代码,展示如何记录 Excel 导入的用时: ' 创建 Stopwatch 实例 Dim stopwatch As New Stopwatc ...