Description
小 π 假期在家无聊,打开了某弹幕直播网站。
突然,有一个精彩的镜头。
小 π 看到了满屏的 6,其中,有 666、也有 666666、也有 6666666666 …
小 π 也想发个弹幕,他打算发 n 个 6。
然而当他按下第一个 6 时,键盘上 6 的键坏了。
这时,弹幕框里只有 1 个 6。
键盘坏了什么的不要紧,先把弹幕发了才是正事。
于是小 π 打算用复制粘贴这类操作来生成这 n 个 6。
具体的说,小 π 电脑的操作系统有唯一的一块剪贴板,初始为空,现在小π 一共有三种操作:
第 1 种操作,全选然后复制。这样会把剪贴板里的内容设置为当前弹幕框内内容。
第 2 种操作,粘贴。会把剪贴板中的内容连接到弹幕框现有的内容后面。
第 3 种操作,backspace。会把在当前弹幕框中删除一个 6。
小 π 很好奇现在生成想要的 n 个 6 至少需要多少次操作,来找到了学信息学竞赛的你。
注意本题时间限制1s
Input
一行一个整数 n。
Output
一行一个整数 ans,表示最少操作次数。
Sample Input 1
0
Sample Output 1
1
Sample Input 2
3
Sample Output 2
3
Data Constraint
其中 6% 的数据,n=2^k,k 为正整数。
其中 24% 的数据,n≤1000。
其中 20% 的数据,内存扩充至768MB。
其中 20% 的数据,时间扩充到3s。
其中 30% 的数据,无特殊限制。
所有数据存在一种划分方法,使得上述范围两两没有交集。
对于 100% 的数据,0≤n≤1000000。
解题思路
考虑dp,f[i]代表从1到i最少需要走几步。状态转移有两种情况,一种是退格,一种是翻倍。可以证明用f[i+j]+j更新f[i]时,j至多需要枚举到3。
代码
#include<bits/stdc++.h>
using namespace std;
int n,f[1000005];
int main(){
scanf("%d",&n);
if(!n) {printf("1");return 0;}
for(int i=1;i<=n+3;++i) f[i]=i;
for(int i=1;i<=n;++i){
for(int j=1;j<=3;++j) f[i]=min(f[i],f[i+j]+j);
for(int j=2;i*j<=n+3;++j) f[i*j]=min(f[i*j],f[i]+j);
}
printf("%d",f[n]);
}
感谢Dilhao大佬的讲解及提示。