[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(fi−1,j,fi−1,j−k∗c[i]∗k)
复杂度是
O
(
N
∗
(
N
∗
K
∗
C
)
∗
K
)
O(N*(N*K*C)*K)
O(N∗(N∗K∗C)∗K) 空间
N
∗
(
N
∗
K
∗
C
)
N*(N*K*C)
N∗(N∗K∗C)需要滚动一下才开得下
[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
<
=
1
e
8
L<=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
)
−
>
f
i
+
1
,
s
∣
S
[
i
+
1
]
f_{i,s}*(2^{cnt[i]}-1)->f_{i+1, s|S[i+1]}
fi,s∗(2cnt[i]−1)−>fi+1,s∣S[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
SNOI 2017 题解
最新推荐文章于 2021-08-29 14:00:28 发布