「SNOI2017」英雄聯盟
阿新 • • 發佈:2018-12-12
題目描述
正在上大學的小皮球熱愛英雄聯盟這款遊戲,而且打的很菜,被網友們戲稱為「小學生」。 現在,小皮球終於受不了網友們的嘲諷,決定變強了,他變強的方法就是:買面板! 小皮球只會玩 NNN 個英雄,因此,他也只准備給這 NNN 個英雄買面板,並且決定,以後只玩有面板的英雄。 這 NNN 個英雄中,第 iii 個英雄有 KiK_iKi 款面板,價格是每款 CiC_iCi Q幣(同一個英雄的面板價格相同)。 為了讓自己看起來高大上一些,小皮球決定給同學們展示一下自己的面板,展示的思路是這樣的:對於有面板的每一個英雄,隨便選一個面板給同學看。 比如,小皮球共有 5 個英雄,這 5 個英雄分別有 0,0,3,2,4&0,0,3,2,4&0,0,3,2,4 款面板,那麼,小皮球就有 3×2×4=24
3×2×4=24 種展示的策略。 現在,小皮球希望自己的展示策略能夠至少達到 MMM 種,請問,小皮球至少要花多少錢呢?
共 10 組資料,第 iii 組資料滿足:N≤max(5,(log2i)4)N\leq\max(5,(\log_2i)^4)N≤max(5,(log2i)4) 100%100\%100% 的資料:M≤1017,1≤Ki≤10,1≤Ci≤199M\leq 10^{17},1\leq K_i\leq 10,1\leq C_i\leq 199M≤1017,1≤Ki≤10,1≤Ci≤199。保證有解。
資料範圍與原題相同,但測試資料由本站會員自制,並非原資料。 時限已按照評測機速度調整,原題時限為 2000 ms。
分析:因為c,k,n的範圍很小,m的範圍很大
所以將錢數作為dp揹包的限制條件,做一次多重揹包
#include<bits/stdc++.h> using namespace std; #define re register int #define ll long long inline void FRE() { freopen(".in","r",stdin); freopen(".out","w",stdout); } inline void FCL() { fclose(stdin); fclose(stdout); } priority_queue<int>mp; const int N=1e5+5; const int mod=1e9+7; const int inf=0x3fffffff; inline ll read() { ll s=0,f=1; char a=getchar(); while(a<'0'||a>'9') { if(a=='-') f=-1; a=getchar(); } while(a>='0'&&a<='9') { s=(s<<3)+(s<<1)+a-48; a=getchar(); } return s*f; } inline void output(int x) { int y=10,len=1; while(y<=x) { y*=10; len++; } while(len--) { y/=10; putchar(x/y+48); x%=y; } } int n,tot; ll dp[N*20],m; int k[N],c[N]; int main() { //FRE(); n=read(); m=read(); for(re i=1;i<=n;i++) { k[i]=read(); } for(re i=1;i<=n;i++) { c[i]=read(); } for(re i=1;i<=n;i++) tot+=k[i]*c[i]; dp[0]=1; for(re i=1;i<=n;i++) { for(re j=tot;j>=0;j--) { for(re kk=1;kk<=k[i];kk++) { if(kk*c[i]>j) break; dp[j]=min(m,max(dp[j-kk*c[i]]*(ll)kk,dp[j])); } } } for(re i=0;i<=tot;i++) { if(dp[i]>=m) { cout<<i; return 0; } } //FCL(); return 0; }