51nod1693 水群
生活随笔
收集整理的這篇文章主要介紹了
51nod1693 水群
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
QwX?(題目提供者) 首先簡化題目,題面的意思就是,當前有一個數(shù)s 操作1是s*=k代價為k,操作2是s--代價為1 求把s從1變到n的最小代價 做法1: 直接暴力記憶化搜索,F(i)表示從1到i用的最小操作數(shù) 則F(i)=min(F(i+1),min{F(k)+n/k|n%k==0}) 當然這樣做肯定過不了 做法2: 考慮把問題轉換成圖論模型,對于每個i 連邊i→i-1邊權為1,連邊i→i*k邊權為k 那么題目就是要求點1到點n的最短路 但是很顯然這樣復雜度還是很高并不能過 做法3: 注意到如果一條邊i→i*k能用若干條邊代替 那么i→i*k這條邊就是沒有意義的 因為那些邊的權值的乘積等于k 即那些邊的權值和小于等于k 因此對于每個i,只用連i→i*p的邊,其中p是質數(shù) 這樣就可以讓邊數(shù)變得很小了 但是0.1s還是過不去 做法4: 既然過不去,就可以想一些別的辦法 考慮在做法3中記錄每一個點的最短路路徑 就是打一個每個點自己最短路上的上一個點的表 那么可以從表中發(fā)現(xiàn),i→i-1的邊不會連續(xù)出現(xiàn)4次以上 而且i→i*p的邊只有當p<=13的時候才有意義 于是又可以刪掉很多邊,邊數(shù)大概是3*10^6條 但是這樣做復雜度還是不夠,用時稍微多于0.1s 做法5: 既然最短路的做法復雜度太高,就可以再換個思路。 重新考慮記憶化搜索的做法,F(i,j)表示從1到i上一條邊的狀態(tài)是j的最少操作數(shù) j=0時上一條邊可以是i→i-1的,否則就是i→i*p的邊 那么F(i,0)=min(min{F(i+k,1)|0<k<5},min{F(i/p,0)|p<13}) 于是這樣做就可以把時間降到最低,從而做出此題 不忘初心 方得始終 PS:后來因為時限問題把時限改成了0.4s,所以做法3就A掉這個題 而且經(jīng)過我自己的測試,做法5是可以在1s之內(nèi)通過10^9的數(shù)據(jù)的 如果大家有興趣可以試著打一下,畢竟也是一個很好的思路 我用了做法4。做法5看不懂。。。做法4一開始我加邊部分點tle了,不加邊就A了。 #include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<queue>
using namespace std;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define clr(x,c) memset(x,c,sizeof(x))
#define qwq(x) for(edge *o=head[x];o;o=o->next)
const int nmax=2e6+5;
const int maxn=1e7+5;
const int inf=0x7f7f7f7f;
struct node{int x,dist;node(int x,int dist):x(x),dist(dist){};node(){};bool operator<(const node&rhs)const{return dist>rhs.dist;}
};
priority_queue<node>q;
int dist[nmax];
const int a[]={2,3,5,7,9,11,13};
int dij(int x){clr(dist,0x7f);dist[1]=0;q.push(node(1,0));node o;int tx,td,to;while(!q.empty()){o=q.top();q.pop();tx=o.x;td=o.dist;if(dist[tx]!=td) continue;rep(i,0,5){to=tx*a[i];if(to<x+10&&dist[to]>td+a[i]){dist[to]=td+a[i];q.push(node(to,td+a[i]));}}if(tx&&dist[tx-1]>dist[tx]+1){dist[tx-1]=dist[tx]+1;q.push(node(tx-1,dist[tx-1]));}} return dist[x];
}
int main(){int n;scanf("%d",&n);printf("%d\n",dij(n));return 0;
}
1693?水群 基準時間限制:0.4?秒 空間限制:524288?KB 分值:?160?難度:6級算法題 ?收藏 ?關注 總所周知,水群是一件很浪費時間的事,但是其實在水群這件事中,也可以找到一些有意思的東西。 比如現(xiàn)在,bx2k就在研究怎樣水表情的問題。 首先,bx2k在對話框中輸入了一個表情,接下來,他可以進行三種操作。 第一種,是全選復制,把所有表情全選然后復制到剪貼板中。 第二種,是粘貼,把剪貼板中的表情粘貼到對話框中。 第三種,是退格,把對話框中的最后一個表情刪去。 假設當前對話框中的表情數(shù)是num0,剪貼板中的表情數(shù)是num1, 那么第一種操作就是num1=num0 第二種操作就是num0+=num1 第三種操作就是num0-- 現(xiàn)在bx2k想知道,如果要得到n(1<=n<=10^6)個表情,最少需要幾次操作。 請你設計一個程序幫助bx2k水群吧。 Input 一個整數(shù)n表示需要得到的表情數(shù) Output 一個整數(shù)ans表示最少需要的操作數(shù) Input示例 233 Output示例 17
轉載于:https://www.cnblogs.com/fighting-to-the-end/p/5874763.html
總結
以上是生活随笔為你收集整理的51nod1693 水群的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: jenkins使用python脚本发送企
- 下一篇: Zotero——一款文献管理工具