51-Nod 1693 水群

                                                          1693 水群

总所周知,水群是一件很浪费时间的事,但是其实在水群这件事中,也可以找到一些有意思的东西。
比如现在,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) {;}
SPFA代码


作者:乌鸦坐飞机
出处:http://www.cnblogs.com/whistle13326/
新的风暴已经出现 怎么能够停止不前 穿越时空 竭尽全力 我会来到你身边 微笑面对危险 梦想成真不会遥远 鼓起勇气 坚定向前 奇迹一定会出现

 
原文地址:https://www.cnblogs.com/whistle13326/p/7511227.html