学习内容:codeforces思维题,dp
1.Absent remainder
模运算的性质:x%y小于y,故找出数组中最小的元素即可
2.回文字串 / [蓝桥杯 2016 省] 密码脱落(P1635)
对于许多动态规划问题,原问题并不能简单的找到状态转移关系,我们可以将问题转换,利用题中的一些性质,如本题中的回文串,正着读与倒着读相同,就将问题转化为易于转移状态的动态规划问题。
3.膜拜(P1564)
线性dp,注意不是n^2算法就一定是二维dp,差用前缀和处理即可
4.windy 数(P2657)
数位dp经典题。这里也是第一次正式接触数位dp,所以本题详细说一下做题思路。
数位dp一般应用在求解[l,r]间满足某种条件(条件一般与数的组成有关)数的个数。一般通过sum[r+1]-sum[l]计算得出。常见定义的状态有dp[i][j],i表示数字有多少位,j表示最高位的数字是什么。
那么对于这道题,易写出转移方程:dp[i][j]=sigma dp[i-1][k](k>=0&&k<=9&&|k-j|>=2)
初始状态有dp[1][i]=1;接下来就可以预处理dp数组了下一个问题就是如何通过预处理的dp数组求出sum[x]。显然我们要先把x逐位分解到dig数组中,设x有len位,那么对于len-1位,我们直接暴力枚举dp[i][j]累加即可,对于第len位的时候,每一位只能枚举到<=dig[i]-1的数(由于dp[len][dig[i]]已经包含了全部以dig[i]开头的数,所以只枚举到dig[i]-1),然后循环处理,注意这里要根据题意适当修改,如本题,如果在枚举到第i位的数字j时,出现abs(j-dig[i+1])>=2时才可以累加。
总而言之,这道数位dp分为两部分,一是状态转移,二是求和sum。在状态转移时我们一般用dp[i][j]来表示一共有i位,最高位为j。求和阶段,我们要先处理前len-1位,直接累加即可;对于第len位,以dig[i]-1为上界枚举,且只有满足题意的数字才会被记入。最后结果为sum(r+1)-sum(l)。‘
5.缩点(P3387)
新知识点:tarjan
tarjan算法:其实就是在dfs的过程中,用dfn数组和low数组分别维护该点的出现时间(即时间戳)和该点能回溯到的最早的栈内的点。初始dfn[i]=low[i],在dfs过程中更新low数组,如果扫完该点所有的边后,该点有dfn[i]=low[i]说明出现了一个强连通分量,即可实现缩点。