agc017f

题目大意

现在你要写出m个长度为n的二进制序列,有一些形如“第i个的第j位必须为x”的限制
对于后面的二进制要>=前面的任意一个二进制

题解

每一个二进制只和和前面的一个二进制有关系,所以有一个很暴力的做法,就是状压前面的一个二进制然后枚举当前的二进制再判断是否合法,这样是 22n 2 2 n 级别的

如何更进一步

我们考虑从本质上思考如何判断两个二进制哪一个大哪一个小

前面的若干位相同,某一位其中一个是0一个是1,后面的位任意
换一种思路呢?
一个二进制>=另一个二进制,这个二进制肯定可以表示成另一个二进制的某一些1前移(可以没有),移完之后再在一些是0的地方换成1(也可以不换)

结合这两种思路我们可以设出一个神奇的dp
f[i][j][S]表示做到第i个二进制,前j位和S相同的方案数(第i个二进制是一位一位放的,所以也可以理解成第i个二进制放了j个0/1)
如果下一位我们要选的和S一样就直接转移到f[i][j+1][S]
如果下一位我们想拿0,但是S的下一位是1那就不合法了
如果下一位我们想拿1,但是S的下一位是0呢
看一看上面,我们这时就有两种方法(前移/添加),并且上面已经说明要先尽量前移,无法前移再考虑添加,所以看一看S后面有没有可以往前移的1,有就前移没有就添加
最后把f[i][n][S]转移到f[i+1][0][S]就可以了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值