[usaco]醜數
阿新 • • 發佈:2017-06-11
truct open 如果 ++ i+1 hid pri names close
思考
首先產生的思路是,用小根堆的最小元素(top)來與 k個數 相乘,之後把結果再扔進小根堆,每次操作得到的即是第k小。 不過要註意一下判重。但是非常悲劇的是 在遇到極限數據的時候TLE了。在思索無果的情況下,偷偷去看了發題解。發現題目的解法還是比較巧妙的。
#include <queue> #include <cstdio> #include <iostream> #define LL long long using namespace std; LL num[105],ans[100005],cnt; struct node{ LL x;這裏附上82分的TLE代碼bool operator < (const node A)const{ return x>A.x; } node(LL x){ this->x=x; } }; priority_queue<node>s; int main(){ LL k,n,i; scanf("%lld%lld",&k,&n); for(register int i=1;i<=k;i++){ scanf("%lld",&num[i]); } s.push(node(1)); while(cnt<=n){ LL x = s.top().x; s.pop(); if(ans[cnt]<x){ ans[++cnt]=x; for(register int i=1;i<=k;i++) s.push(node(num[i]*x)); } } printf("%lld",ans[n+1]); }
題解的思路是什麽呢? f[i]表示第i小 那麽f[i]一定大於f[i-1] 我們要做的是 f[i]大於f[i-1] 並盡量的小(讀者:這不是廢話嗎?)
其次 f[i]一定是這k個數中的某個數 乘 f[i-1]或者f[i-2]或者f[i-3]....得來的,那麽思路就出來了。 但是這三層循環還是有可能TLE。所以要進一步優化.
很容易發現滿足條件的醜數x*a[j]>f[i-1],一定滿足條件,x*a[j]>f[i-2];於是我們就可以從滿足x*a[j]>f[i-2]的醜數x的位置往後枚舉,找到滿足條件x*a[j]>f[i-1]的醜數。
然後和min比較。
#include <cstdio> #include <iostream> typedef unsigned long long ll; using namespace std; const int maxn=100011; ll Num[123],f[maxn],jl[maxn]; ll n,MIN,k; int main(){ scanf("%lld%lld",&k,&n); for(int i=1;i<=k;i++) scanf("%lld",&Num[i]); f[0]=1; for(int i=1;i<=n;i++){ MIN=3e9; for(int j=1;j<=k;j++){ //為什麽要jl[j]++ 因為如果不加的話 到f[i+1] f[jk[j]]*Num[j] 一定也是<=f[i] //其次 s[j]存的是a[j]至少與第幾小醜數相乘才能得到一個比f[i-1]大的醜數 while(Num[j]*f[jl[j]]<=f[i-1]) jl[j]++; MIN = min(MIN,Num[j]*f[jl[j]]); } f[i] = MIN; } printf("%lld",f[n]); }
[usaco]醜數