BZOJ 4762: 最小集合

这是一道关于计算非空集合满足特定条件的子集数量的问题。集合元素需满足and和为0且非空子集中仅自身满足条件。给定集合S的大小n和元素ai,要求输出合法子集数模1e9+7的结果。题目提供了一种状态转移的动态规划解决方案,通过变换集合和定义状态f[i][j][k],表示处理到第i个数时,前部分or和为j,期望后续部分包含k的情况。通过状态转移,将复杂度优化至n*3^m。
摘要由CSDN通过智能技术生成

Description

定义一个非空集合是合法的,当且仅当它满足以下两个条件。
1、集合内所有元素and和为0
2、它的非空子集中仅有它本身满足1
给出一个集合S,求它的合法非空子集数。

Input

第一行一个正整数n,表示|S|
第二行n个非负整数ai,表示集合内的元素。
n≤1000,ai<1024

Output

一个整数,表示S的合法非空子集数。答案可能很大,请mod 1e9+7之后输出。

Sample Input

4

1 2 4 4

Sample Output

5

样例解释:满足条件的集合为{1,2},{1,4},{1,4},{2,4},{2,4}

分析

转自栋爷的博客

先把给定集合所有数取反。
比如有效位数是4位,1101就变成0010。
那么问题变成,所有元素or和为1023,而去掉任意一个元素后or和均不为1023。
那么接下来我们来设一个诡异的状态。
因为要知道去掉一个人元素会不会使or和为1023,因此我们前后都要知道。
可以设一个f[i,j,k]表示做完了i个数,前面选择的一些数or和为j,我们希望后面选出的数or和为k。
然而随便推一推都觉得不会转移啊。。
这时赶紧改一下状态,设f[i,j,k]表示做完了i个数&

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值