这里会显示出您选择的修订版和当前版本之间的差别。
后一修订版 | 前一修订版 | ||
2020-2021:teams:legal_string:jxm2001:contest:cf_666_div._1 [2020/09/04 11:42] jxm2001 创建 |
2020-2021:teams:legal_string:jxm2001:contest:cf_666_div._1 [2020/09/04 15:34] (当前版本) jxm2001 |
||
---|---|---|---|
行 7: | 行 7: | ||
==== 题意 ==== | ==== 题意 ==== | ||
+ | 给定 $n$ 堆石头和两个玩家 $A,B$,$A$ 先手。 | ||
+ | 每次轮到某个玩家时,该玩家需要选择一个非空且上一轮没有被另一个玩家拿过的堆,拿走一个石头。 | ||
+ | |||
+ | 如果该玩家无法操作,则该玩家败北。问谁有必胜策略。 | ||
==== 题解 ==== | ==== 题解 ==== | ||
+ | 设最大的堆有 $v$ 个石头,总共有 $s$ 个石头。 | ||
+ | 首先不难得出结论:如果 $v\gt \frac n2$,则 $A$ 有必胜策略。 | ||
- | <hidden 查看代码> | + | 否则如果 $s$ 为偶数,设 $s=2k$,构造石头序列,使得所有属于同一个堆的石头相邻。 |
- | <code cpp> | + | |
- | </code> | + | 例如,设现有 $3$ 个堆,分别有 $3,3,4$ 个石头,则得到序列 $1,1,1,2,2,2,3,3,3,3$。 |
- | </hidden> | + | |
+ | 于是可以保证第 $i$ 个石头与第 $i+n$ 个石头不属于同一个堆,于是将其两两配对。每次 $A$ 选取石头后, $B$ 选择对应石头即可。 | ||
+ | |||
+ | 所以上述情况 $B$ 有必胜策略。 | ||
+ | |||
+ | 如果 $s$ 为奇数,设 $s=2k+1$,根据假设 $v\le \lfloor \frac n2\rfloor=k$。于是 $A$ 任意取一个石头后 $s=2k$ 仍然满足 $v\le \frac n2$。 | ||
+ | |||
+ | 于是该情况转化为 $s$ 为偶数的情况,此时 $A$ 转变为后手,于是 $A$ 有必胜策略。 | ||
===== C. Monster Invaders ===== | ===== C. Monster Invaders ===== | ||
行 33: | 行 45: | ||
如果对当且楼层 $\text{boos}$ 造成伤害但未将 $\text{boos}$ 杀死则立刻强制转移到其他楼层。每次转移楼层(不管是主动还是强制转移)均花费 $d$。 | 如果对当且楼层 $\text{boos}$ 造成伤害但未将 $\text{boos}$ 杀死则立刻强制转移到其他楼层。每次转移楼层(不管是主动还是强制转移)均花费 $d$。 | ||
- | 问杀死所有怪物(包括 $\text{boos}$)的最小费用。 | + | 问杀死所有怪物(包括 $\text{boos}$)的最小费用。(保证 $r_1\le r_2\le r_3$) |
==== 题解 ==== | ==== 题解 ==== | ||
+ | 假如某时刻在第 $i$ 层,第 $i-1$ 层的 $\text{boos}$ 还有一点 $\text{Hp}$,但 $j\lt i-1$ 的怪物已经全部消灭。 | ||
+ | 如果将第 $i-1$ 层作为终点,则必须从第 $i$ 层前往第 $i+2$ 层,将第 $i+2$ 层及以上的怪物全部消灭。 | ||
+ | |||
+ | 然后再从第 $i+1$ 层回到第 $i$ 层,再回到第 $i-1$ 层。所以从此刻起一共需要在第 $i-1$ 到第 $i+1$ 层间转移 $3$ 次。 | ||
+ | |||
+ | 事实上,先从第 $i$ 层回到第 $i-1$ 层消灭 $\text{boos}$,再回到第 $i$ 层,最后前往 $i+1$ 层也只需要转移 $3$ 次。 | ||
+ | |||
+ | 于是可以用第二种方案替代第一种方案。 | ||
+ | |||
+ | 另外,由于第二种方案保证经过第 $i$ 层两次,于是可以保证杀死第 $i$ 层所有怪物,于是有 $j\lt i+1$ 的怪物已经全部消灭。 | ||
+ | |||
+ | 于是只要第 $i+1$ 层存在,第 $i-1$ 层一定可以不是终点,且可以认为之前必须先杀死 $j\lt i-1$ 层的所有怪物。 | ||
+ | |||
+ | 于是只需要考虑将第 $n$ 层和第 $n-1$ 层作为终点的情况。设 $\text{dp}(i,0/1)$ 表示已经到达 $i+1$ 层,第 $i$ 层 $\text{boos}$ 还剩余 $0/1 \text{Hp}$ 的情况。 | ||
+ | |||
+ | 时间复杂度 $O(n)$。 | ||
<hidden 查看代码> | <hidden 查看代码> | ||
<code cpp> | <code cpp> | ||
+ | const int MAXN=1e6+5; | ||
+ | int a[MAXN]; | ||
+ | LL dp[MAXN][2]; | ||
+ | int main() | ||
+ | { | ||
+ | LL n=read_int(),r1=read_int(),r2=read_int(),r3=read_int(),d=read_int(); | ||
+ | _for(i,0,n)a[i]=read_int(); | ||
+ | _rep(i,1,n)dp[i][0]=dp[i][1]=1e18; | ||
+ | dp[1][0]=r1*a[0]+r3,dp[1][1]=min((a[0]+1)*r1,r2); | ||
+ | _for(i,1,n){ | ||
+ | dp[i+1][0]=min(dp[i+1][0],d+dp[i][0]+a[i]*r1+r3); | ||
+ | dp[i+1][0]=min(dp[i+1][0],3*d+dp[i][1]+r1+min(r2+r1,r1*a[i]+min(2*r1,r3))); | ||
+ | dp[i+1][1]=min(dp[i+1][1],min(d+dp[i][0],3*d+r1+dp[i][1])+min(r2,(a[i]+1)*r1)); | ||
+ | } | ||
+ | enter(min(dp[n][0],2*d+dp[n-1][1]+r1+a[n-1]*r1+r3)); | ||
+ | return 0; | ||
+ | } | ||
</code> | </code> | ||
</hidden> | </hidden> |