1 条题解
-
0
自动搬运
来自洛谷,原作者为

菲斯斯夫斯基
几时归去,作个闲人。对一张琴,一壶酒,一溪云。搬运于
2025-08-24 22:56:16,当前版本为作者最后更新于2024-05-07 10:47:07,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
P10259 [COCI 2023/2024 #5] Piratski kod 题解
upd:无聊的时候突然发现有一条转移方程写错了。
前言
非常好 dp,使我的大脑旋转。仍然是教练放在模拟赛里的题,考场时一眼没思路就跳了。结果其他大佬都是一眼秒,输了。/kk
思路
感觉应该还是可以看出来要用 dp 的,但是难在设计状态。
便于描述,以下将「没有两个连续的 的序列」称为「散块」;将「末尾的两个字符都是 的序列」称为「整块」。
不难发现一个价值不为 的二进制序列其实就是一个整块加上一个散块。
所以问题转化为如何求散块和整块的价值。
按照套路,我们设计 的含义为 长度为 的散块,结尾为 的价值总和。注意这里是价值总和,例如长度为 ,结尾为 求的就是 和 的价值之和。
考虑怎么转移。显然转移应该从 增加 得到 。增加一个 好办,因为不会增加价值,所以得到第一条转移方程:。增加一个 会对每一条序列都增加 的价值。
注意到是每一条,所以还要再设计一个数组 ,意思是长度为 ,结尾为 的散块的个数。 数组的转移是简单的,注意不能连续放两个 就行:,。
回到刚才 数组的转移,现在已经求出了序列的个数,转移方程就出来了:$f_{i,1}=f_{i-1,0}+num_{i-1,0}\times \text{Fib}_{i+1}$。注意一下 的下标。
好了,现在散块算完了,该算整块了。整块和散块的计算是类似的。定义 为长度为 的整块的价值总和, 为长度为 的整块个数。
根据上面对整块的定义,可以发现一个以 结尾的散块在末尾加上不计算价值的 就成为了整块。同时两个整块拼接在一起仍然是整块。所以为了避免重复计算或者漏算,计算 时将这个整块拆分成一个 前面计算过的整块 和 一个 用散块加 形成的整块。
状态转移方程可以推理得到:
$$dp_i=\sum\limits_{j=1}^{i-1}f_j\times s_{i-j-1}+dp_{i-j-1}\times num_{j,1} $$其中 枚举的是散块的长度。任意一个整块和任意一个散块合并都会产生贡献,所以用到乘法原理。
数组的转移是类似的:$s_i=\sum\limits_{j=1}^{i-1}s_{i-j-1}\times num_{j,1}$。
好了,现在散块和整块的价值都计算完毕。最后的价值不为 的序列是由一个整块和散块合并而成的,枚举整块的长度即可:
$$ans_i=\sum\limits_{j=2}^{i}dp_j\times(num_{i-j,0}+num_{i-j,1}) $$注意散块贡献的是个数而不是价值。
如果你觉得这篇题解写的不错,可以留下一个点赞,谢谢~
代码
代码的实现并没有难度,把上面的几个转移方程搬上去就行。
#include<bits/stdc++.h> #define int long long using namespace std; const int N=5010,mod=1e9+7; int n; int f[N][2],num[N][2],dp[N],fib[N]={0,1,1},s[N]; signed main() { cin>>n; for(int i=3;i<=n;i++) fib[i]=fib[i-1]+fib[i-2],fib[i]%=mod; num[0][0]=1; for(int i=1;i<=n;i++) { f[i][0]=f[i-1][0]+f[i-1][1],f[i][0]%=mod; f[i][1]=f[i-1][0]+fib[i+1]*num[i-1][0],f[i][1]%=mod; num[i][0]=num[i-1][0]+num[i-1][1],num[i][0]%=mod; num[i][1]=num[i-1][0]; } s[0]=1; for(int i=1;i<=n;i++) for(int j=1;j<i;j++) { dp[i]+=f[j][1]*s[i-j-1]+dp[i-j-1]*num[j][1],dp[i]%=mod; s[i]+=s[i-j-1]*num[j][1],s[i]%=mod; } for(int i=1;i<=n;i++) { int ans=0; for(int j=2;j<=i;j++) ans+=dp[j]*(num[i-j][0]+num[i-j][1]),ans%=mod; printf("%lld ",ans); } return 0; }
- 1
信息
- ID
- 9954
- 时间
- 2000ms
- 内存
- 512MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者