思路讲解
1 | // 在这两个位置的s和p等价于点 |
然后就是不能有p出现在s之后,不能有s出现在p之后,非常简单吧
AC代码
1 |
|
1 | // 在这两个位置的s和p等价于点 |
然后就是不能有p出现在s之后,不能有s出现在p之后,非常简单吧
1 | #include <iostream> |
我想到一个背景故事,就是说每条龙都想有和自己的朋友不同的涂装,但是编号越大的涂装越贵,龙龙们想用编号比较小的涂装达成这一目的,但是龙龙们不知道怎样组合才好,于是找到了你。
多用构造之方法,少用特判之方法,毕竟是构造题嘛。
https://codeforces.com/contest/2049/submission/300064440
1 | #include <iostream> |
WA https://codeforces.com/contest/2049/submission/300052744
1
5 3 5
2 1 2 1 0 (A[2]=1,但应该是0)
唉,很久以前写的,已经看不懂什么意思了
1 | #include <iostream> |
我们先考虑不向左循环移动的情况,那么实际上这个块要么从左边转移过来,要么从上边转移过来。
那么如果加了向左循环移动那?首先dp里存的东西变成了到达此块的总代价即题目中的(kx+y)(y即经过之点的权重之和)
转移的话,从上面转移还是简单,就是要多加一个 K* 向左循环移动次数就行。
如果需要从左边转移,那么要注意,此时只有第一个块需要加一个 K* 向左循环移动次数,后面的块是不需要的,这个要小心一点。
(其实严格来说只有第一行第一个块需要加,因为后面的块都是先从上面转移下来,已经加过一个这个了,不过我也懒得这么严格,因为我的左边界是无穷大除了第一行第一个块旁边是0)
https://codeforces.com/contest/2049/submission/299989686
1 | #include <iostream> |
这个转移公式不是每一次都要+kK,如果是从一个已经加过kK的地方转移过来的,那么就不用加了
1 | for(int i=1;i<=n;++i){ |
https://codeforces.com/contest/2049/submission/299988064
TLE,因为memset()。
1 | // memset(dp, 0x3f, sizeof(dp)); |
数位dp记忆化搜索做法
1 | // dp装的在top位为n的情况下,第i位符合要求的数字数量 |
以下为思维做法,了解数位dp后觉得有点玄学
我的思路就是先算出1~两个数之间的snake number数量,再将两者相减。
我们以1~90011来解释我们的运算过程
90011可以拆成首位为0~9的情况,其中2~8的计算相对简单,首位已经确定,后面每位有首位种选择,snake number 数量就是 首位^后面的位子数
0的情况就是
1 | // 假设首位为0情况 |
9的情况就是和2~8一样正常算,然后把不可行的情况数剪掉
1 | if(i==s[0]-'0'){ |
具体而言如下图

AC https://atcoder.jp/contests/abc387/submissions/61678607
1 | #include <iostream> |
AC https://atcoder.jp/contests/abc387/submissions/61423141
1 | #include <iostream> |