Description
總所周知,水群是一件很浪費時間的事,但是其實在水群這件事中,也可以找到一些有意思的東西。
比如現在,bx2k就在研究怎樣水表情的問題。
首先,bx2k在對話方塊中輸入了一個表情��,接下來,他可以進行三種操作。
第一種,是全選複製,把所有表情全選然後複製到剪貼簿中。
第二種,是粘貼,把剪貼簿中的表情粘貼到對話方塊中。
第三種,是退格,把對話方塊中的最後一個表情刪去。
假設目前的交談框中的表情數是num0,剪貼簿中的表情數是num1,那麼第一種操作就是num1=num0
第二種操作就是num0+=num1
第三種操作就是num0–
現在bx2k想知道,如果要得到n(1<=n<=10^6)個表情,最少需要幾次操作。
請你設計一個程式協助bx2k水群吧。
Input
一個整數n表示需要得到的表情數
Output
一個整數ans表示最少需要的運算元
Input樣本
233
Output樣本
17
思路
我們每一次獨立的操作無疑就是 複製 1 次 + 粘貼 x 次 + 退格 y 次 ,因為連續複製兩次顯然無意義,並且退格在粘貼之前與之後都是同樣的效果。
於是題目相當於:當前有一個數 x x ,操作 1 1 是 x=x×k x=x \times k ,代價為 k k ;操作 2 2 是 x=x−1 x=x-1 ,代價為 1 1 ,求從 1 1 到 n n 的最小代價。
顯然我們可以建圖求最短路即為最終的結果,但是 x=x×k x=x \times k 所產生的邊數太多,經過思考我們可以將 k k 質因子分解,最終變為 x=x×[2,3,5,7...] x=x \times [2,3,5,7...] ,這樣便消除了其中的冗餘邊。
經過測試取前 5 5 個質數就可以保證答案~
AC 代碼
#include<bits/stdc++.h>using namespace std;const int N = 1e6+10;#define inf 0x7f7f7f7fint prime[]= {2,3,5,7,11};bool vis[N];int dist[N];int n,maxn;int spfa(int s,int e){ queue<int> sk; maxn = n+10; for(int i=0; i<maxn; i++) { dist[i] = inf; vis[i] = false; } dist[s] = 0; vis[s] = true; sk.push(s); while(!sk.empty()) { int u = sk.front(); sk.pop(); vis[u] = false; if(u-1>0&&dist[u-1]>dist[u]+1) { dist[u-1] = dist[u] + 1; if(!vis[u-1]) { vis[u-1] = true; sk.push(u-1); } } for(int i=0; i<5&&prime[i]*u<maxn; i++) { int to = prime[i]*u; int cost = prime[i]; if(dist[to]>dist[u]+cost) { dist[to] = dist[u]+cost; if(!vis[to]) { vis[to]=true; sk.push(to); } } } } return dist[e];}int main(){ scanf("%d",&n); printf("%d\n",spfa(1,n)); return 0;}