直接按性价比排序然后贪心,优先选前面的,由于可以超过,所以要判断使用当前的超过后的sum是多少兵更新下ans。
今天看了学长的题解后,发现不同的思路,f[i]表示能组成1<<(i-1)最小的cost,然后像按二进制从高位到低位处理,也要考虑用当前位超过
第二份代码也写了。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxl 40
using namespace std;
int n,m;
struct bot
{
long long v,c;
}a[maxl];
long long ans;
bool cmp(const bot &x,const bot &y)
{
return x.c*y.v<y.c*x.v;
}
inline void prework()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
a[i].v=1<<(i-1);
scanf("%I64d",&a[i].c);
}
sort(a+1,a+1+n,cmp);
}
inline void mainwork()
{
int res=m,l=1;
long long sum=0;
ans=0;
while(res>0 && l<=n)
{
sum+=res/a[l].v*a[l].c;
res%=a[l].v;
if(res==0)
if(ans==0)
ans=sum;
else
ans=min(ans,sum);
else
if(ans==0 || sum+a[l].c<ans)
ans=sum+a[l].c;
l++;
}
}
inline void print()
{
printf("%I64d",ans);
}
int main()
{
prework();
mainwork();
print();
return 0;
}
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxl 40
using namespace std;
int n,m,cnt;
struct bot
{
long long v,c;
}a[maxl];
long long f[maxl],ans;
inline void prework()
{
ans=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
a[i].v=1<<(i-1);
scanf("%I64d",&a[i].c);
}
f[1]=a[1].c;
for(int i=2;i<=n;i++)
f[i]=min(a[i].c,f[i-1]*2);
cnt=n;
while(1<<(cnt-1)<=m)
{
cnt++;
if(1<<(cnt-1)<=m)
f[cnt]=f[cnt-1]*2;
}
}
inline void mainwork()
{
long long sum=0;
for(int i=cnt;i>=1;i--)
{
if(m&(1<<(i-1)))
sum+=f[i],m^=(1<<(i-1));
if(m==0)
{
if(ans>0)
ans=min(ans,sum);
else
ans=sum;
break;
}
if(ans>0)
ans=min(ans,sum+f[i]);
else
ans=sum+f[i];
}
}
inline void print()
{
printf("%I64d",ans);
}
int main()
{
prework();
mainwork();
print();
return 0;
}