edu154

edu 154

总评:这种题见多了自然而然可能就会了,虽然说这次排名很低,但是我觉得很有价值,T2 因为想偏了方向所以很久才过,T3 赛时直接没过,想的方向是对的,但是实现寄了,T4 \(dp\) 没有想到,分成两段来考虑也没有想到/ll(感觉分成两段考虑的思路好像很好想

A

发现 \(31\)\(13\) 都是质数,判断一下前后位置即可

B

我们先把题意简化,如果 \(a[i]=b[i]=0\) 那么当前这个为 \(0\) ,如果等于 \(1\) ,那么这个点为 \(1\) ,否则为 \(?\)

其实就是想用 \(1\)\(0\) 把整个区间覆盖

做法一:

发现第一位一定为 \(0\) ,且最后一位一定为 \(1\) ,考虑找到一个位置 \(i\) 使得 \(i\) 这一位为 \(0\) ,并且 \(i+1\) 这一位为 \(1\) 那么这个问题就解决了

做法二:

我在赛时想到了这种,但是因为少了一点点转化被我 pass 了,最后写了好久,最后才用 \(dp\) 转移

因为我们发现两个 \(0\) 可以覆盖一个区间,设 \(dp[i]\) 表示做到第 \(i\) 位,解决了多少个 \(?\)

显然转移为 $dp[j]\to dp[i] $ 前提是 \(i\)\(j\) 为同一个数字

要注意一个点,如果 \(i\)\(i-1\) 都是 \(1\) 或者 \(0\) 中的任意一个,那么 \(dp[i]=\max(dp[i],d[i-1])\)

最后判断一下 \(dp[n]\) 是不是等于 \(?\) 的总量就可以了

C

最先开始想的模拟,发现非常难写,最后遗憾离场

考虑加入的第 \(x\) 个数,他可以比上一个数大,也可以比上一个数小,我们目前没法判断

\(f[i]\) 表示当前栈里的第 \(i\)\(+\) 是比上一位大还是比上一位小,大就是 \(1\) ,反之为 \(0\)

  1. \(s[x]=+\) ,那么加入一个数 \(2\) ,并且把他丢进 \(f\)
  2. \(s[x]=-\) ,直接把栈里最后一个弹出即可
  3. \(s[x]=1\) ,如果 \(f[stk[top]]=1\) ,那么无法构造,否则从这一位到上一个 \(1\) 的位置上的 \(f[i]\) 都赋值 \(1\) 即可 ,如果找到一个为 \(0\) 的,直接输出 \(NO\) 即可
  4. \(s[x]=2\) ,那么说明最后这一位为 \(0\) ,但如果 \(f[stk[top]]=1\) 那么说明无法构造

Code

D

感觉 D 比 C 还简单

发现数组是一会上升一会下降的,我们想把他改成全上升

对于一个序列,我们有两种方法把他给变成上升

  1. 直接把下降的序列乘一个负数变成上升
  2. 先把上升的序列改成下降,在花费 \(1\) 的代价,把他翻转

这时候可以想到把整个序列分成两段,前一段变成下降,后一段变成上升,最后对于每一个分界点取 \(min\) 即可

为什么是两段?因为三段即以上会在两段的基础上,多花费一些代价

Code

E

看到求代价,那么显然有两种做法(\(dp\) 或者数学计数)

做法一(\(dp\)):

有一个贪心的策略,每次往后选,如果有长度为 \(k\) 并且符合条件的子串,代价就 \(+1\)

可以想到一个 \(dp[i][j]\) 表示前 \(i\) 个数极长的符合条件的长度为 \(j\) 的后缀的方案数,\(g[i][j]\) 表示前 \(i\) 个数极长的符合条件的长度为 \(j\) 的后缀的代价之和

转移的话考虑第 \(i+1\) 位填什么

可以填除了 \(j\) 以外的其他 \(k-j\) 个数,\(dp[i][j]\times(k-j)\to dp[i+1][j]\)

还可以填 \(j\) 里面出现过的数,\(dp[i][j]\to dp[i][p](p\in[1,j])\)

\(g\) 的转移同理

要注意的是 \(f[i-1][k-1] \to f[i][k]\) 的转移,因为对于 \(i+1\) 时,我们还需要用 \(0\) 这个数,并且 \(0\) 就表示 \(i\) 这一位什么都没有填,正好 \(i\) 这个位置上已经填过别的东西,所以直接把 \(f[i-1][k-1]\to f[i][0]\) 即可

以及注意 \(f[i-1][k-1]+g[i-1][k-1] \to g[i][0]\) 因为我们只算最后一个 \(k\) 填上的贡献,前面的如何答案已经统计过了,所以不用管,所以方案数就是贡献

Code

做法二(数学计数):

\(dp[i]\) 表示考虑了前 \(i\) 个数,并且有一个长度为 \(k\) 符合条件的以 \(i\) 结尾的贡献次数。

如果不考虑答案的重复统计,我们可以使 \(dp[i]=k!\times k^{i-k}\) 作为答案,前 \(i-k\) 个可以随便选,从 \(i-k+1\)\(i\) ,保证是 \(k\) 个数都出现过即可

但是根据上面贪心的选择方式,可能会出现选择的这个 \(k\) 和前面选择过的子串产生冲突,那么这个时候这里的答案就要减去冲突的部分,即 \(f[j]\times (i-j)!(j\in [i-j+1,i])\)

最后统计答案就是 \(ans=\sum_{i=1}^{n}f[i]\times k^{n-i}\) ,因为剩下的随便选就好了,这里不会和后面冲突的原因是,前面都不一样(一样的都没容斥掉了),后面必然不会冲突。

Code

posted @ 2023-09-01 16:35  taozhiming  阅读(24)  评论(0)    收藏  举报