题目描述
正在上大学的小皮球热爱英雄联盟这款游戏,而且打的很菜,被网友们戏称为「小学生」。
现在,小皮球终于受不了网友们的嘲讽,决定变强了,他变强的方法就是:买皮肤!
小皮球只会玩 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)Nleqmax(5,(log_2i)^4)N≤max(5,(log2i)4)
100%100\%100% 的数据:M≤1017,1≤Ki≤10,1≤Ci≤199Mleq 10^{17},1leq K_ileq 10,1leq C_ileq 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;
}