总所周知,水群是一件很浪费时间的事,但是其实在水群这件事中,也可以找到一些有意思的东西。
比如现在,bx2k就在研究怎样水表情的问题。
首先,bx2k在对话框中输入了一个表情,接下来,他可以进行三种操作。
第一种,是全选复制,把所有表情全选然后复制到剪贴板中。
第二种,是粘贴,把剪贴板中的表情粘贴到对话框中。
第三种,是退格,把对话框中的最后一个表情删去。
假设当前对话框中的表情数是num0,剪贴板中的表情数是num1,
那么第一种操作就是num1=num0
第二种操作就是num0+=num1
第三种操作就是num0--
现在bx2k想知道,如果要得到n(1<=n<=10^6)个表情,最少需要几次操作。
请你设计一个程序帮助bx2k水群吧。
Input
一个整数n表示需要得到的表情数
Output
一个整数ans表示最少需要的操作数
Input示例
233
Output示例
17
三种操作
一是复制 二是粘贴 三是删除
当前有一个表情
复制 粘贴 粘贴 就有三个表情了 一共三次操作
若有两个表情
复制 粘贴 粘贴 就有6个表情 三次操作 得到 2*3个表情
那么 我们可以把 第一和第二个操作合并 看成一个操作
当前有 a 个表情 可以经过 k次操作 变成a*k个表情
还有一个操作就是删除 没什么好说的
题目要让求 1变成 n 的最小次数 那么 这就是一个最短路模型
通过上面的操作 我们可以这样建图
i->i*k 操作次数为 k
i->i-1 操作次数为 1
但是复杂度太高 并不能在0.4s内通过
我们可以发现 1->6 有一条边
2->6 也会有一条边
注意到如果一条边i→i*k能用若干条边代替
那么i→i*k这条边就是没有意义的
因为那些边的权值的乘积等于k
即那些边的权值和小于等于k
所以 我们可以替换许多没有用的边
因此对于每个i,只用连i→i*p的边,其中p是质数
这个时候 0.4s差不多了 但是题目之前时限是 0.1s (后来改为0.4s)
所以我们记录最短路的路径 发现最有质数p<=13时才有意义
0.4s 无压力 但是0.1s还不行 需要用dp (我并不会T_T)
1 #include <queue> 2 #include <cstdio> 3 #include <cctype> 4 #include <cstring> 5 6 const int INF=0x3f3f3f3f; 7 const int MAXN=1000010; 8 9 int n; 10 11 int dis[MAXN],q[MAXN],prim[11]={0,2,3,5,7,9,11,13}; 12 13 bool vis[MAXN]; 14 15 inline void read(int&x) { 16 int f=1;register char c=getchar(); 17 for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar()); 18 for(;isdigit(c);x=x*10+c-48,c=getchar()); 19 x=x*f; 20 } 21 22 inline int min(int a,int b) {return a<b?a:b;} 23 24 int hh() { 25 read(n); 26 memset(dis,INF,sizeof dis); 27 int head=0,tail=0; 28 q[++tail]=1; 29 dis[1]=0; 30 while(head!=tail) { 31 int u=q[++head]; 32 vis[u]=false; 33 if(head==MAXN) head=0; 34 for(int i=1;i<=7;++i) { 35 int v=u*prim[i]; 36 if(v>n+20) break; 37 if(v<n+20&&dis[v]>dis[u]+prim[i]) { 38 dis[v]=dis[u]+prim[i]; 39 if(!vis[v]) { 40 vis[v]=true; 41 q[++tail]=v; 42 if(tail==MAXN) tail=0; 43 } 44 } 45 } 46 if(u&&dis[u-1]>dis[u]+1) { 47 dis[u-1]=dis[u]+1; 48 if(!vis[u-1]) { 49 vis[u-1]=true; 50 q[++tail]=u-1; 51 if(tail==MAXN) tail=0; 52 } 53 } 54 } 55 printf("%d ",dis[n]); 56 return 0; 57 } 58 59 int sb=hh(); 60 int main(int argc,char**argv) {;}