SNOI 2017 题解

[SNOI2017]礼物
直接矩阵乘就好了,需要维护 i k i^k ik,转移要用二项式展开一些
[SNOI2017]英雄联盟
直接背包不行,转换一些, f i , j f_{i,j} fi,j表示到i,花 j 元,最多能凑到多少
f i , j = m a x ( f i − 1 , j , f i − 1 , j − k ∗ c [ i ] ∗ k ) f_{i,j} = max(f_{i-1, j}, f_{i-1,j-k*c[i]}*k) fi,j=max(fi1,j,fi1,jkc[i]k)
复杂度是 O ( N ∗ ( N ∗ K ∗ C ) ∗ K ) O(N*(N*K*C)*K) O(N(NKC)K) 空间 N ∗ ( N ∗ K ∗ C ) N*(N*K*C) N(NKC)需要滚动一下才开得下
[SNOI2017]遗失的答案
首先 N / = G , L / = G N/=G, L/=G N/=G,L/=G对于原问题是等价的
然后令 L = ∏ p i c i L=\prod p_i^{c_i} L=pici,选出来的数 p i p_i pi的指数最大应为 c i c_i ci,最小为0
因为 L &lt; = 1 e 8 L&lt;=1e8 L<=1e8所有 p 最多有 8 个
我们用两个二进制数s1, s2记录状态, 表示每个p的最小指数是不是0,最大指数是不是 c i c_i ci,s 表示它们两个合起来的状态, 然后把相同的归到一类,发现最多600多个,然后就可以 DP 了
f i , s f_{i,s} fi,s 表示选到第 i 类,当前状态为 s 的方案数, c n t [ i ] cnt[i] cnt[i]表示第i类的个数
转移就是枚举下一位选或者不选 f i , s ∗ ( 2 c n t [ i ] − 1 ) − &gt; f i + 1 , s ∣ S [ i + 1 ] f_{i,s}*(2^{cnt[i]}-1)-&gt;f_{i+1, s|S[i+1]} fi,s(2cnt[i]1)>fi+1,sS[i+1]
怎么强制选一个数呢?我们发现可以先强制不选它,然后最后把它强制加进去
于是需要从后往前做一个后缀的DP, 然后不选某个数的方案数就是前后平起来
发现拼接的过程是一个或卷积,于是FWT 就可以了
于是用 a n s i , s ans_{i,s} ansi,s表示强制不选 i,状态为s 的方案数
如果 S [ i ] ∣ s = 11111... S[i]|s=11111... S[i]s=11111...那么就可以把 a n s i , s ans_{i,s} ansi,s的答案加到强制选i的答案中
因为i这一类至少需要选一个数,其它的爱选不选,所以答案还要乘上 2 c n t [ i ] − 1 2^{cnt[i]-1} 2cnt[i]1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FSYo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值