高校联盟 计蒜客 超市购物(二分+贪心)

超市有n种不同的商品(从1开始编号),第i种商品有一个基本花费b_ibi

小白要来买东西,如果小白买了k件商品,编号分别为x_1x1x_2x2、..、x_kxk,那么物品x_jxj的花费为b_{x_j}bxj+x_j*kxjk (1<=j<=k)。也就是说,物品的花费等于它的基本花费加上它的编号乘上k。

小白想要在花费不超过SP的情况下买尽量多的物品。注意,一种物品最多买一件。

输入

第一行两个整数,n和SP(1<=n<=10^5105,1<=SP<=10^9109),含义如上。

第二行n个整数b_1b1b_2b2,,,b_nbn (1<=b_ibi<=10^5105).

输出 

将小白最多买的物品数k和买k件物品的最少花费输出到一行

样例输入

3 11
2 3 5

样例输出

2 11 
 
 
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
ll n,sp,sum;
const int maxn=1e5+5;
ll b[maxn],c[maxn];
bool solve(ll k)
{
    sum=0;
    for(ll i=1;i<=n;i++)
    {
        c[i]=b[i]+i*k;
    }
    sort(c+1,c+n+1);
    for(ll i=1;i<=k;i++)
    {
        sum+=c[i];
        if(sum>sp) return false;
    }
    return true;
}
int main()
{
    scanf("%lld%lld",&n,&sp);
    for(ll i=1;i<=n;i++)
        scanf("%d",&b[i]);
//   for(int i=1;i<=n;i++)
//   {
//       if(solve(i)) cout<<i<<endl;
//   }
   ll l=1,r=n; ll k=0;
   ll m=0,ans=0;
   while(l<r)
   {//cout<<l<<' '<<r<<endl;
       m=l+(r-l+1)/2;
      //m=(l+r+1)>>1;
       if(solve(m))
       {   k=m;
           ans=sum;
           l=m;
       }
       else
       {
           r=m-1;
       }
   }
   printf("%lld %lld\n",k,ans);
   return 0;
}
/*
3 11
2 3 5
*/

  • 我写的蜜汁二分,第一次m=l+(l-r)/2;  l=m+1;r=m;
  • 百发百wa,虽然样例是过的,改成m+1,l,r都-1才能过,心情复杂
  •  131072K

超市有n种不同的商品(从1开始编号),第i种商品有一个基本花费b_ibi

小白要来买东西,如果小白买了k件商品,编号分别为x_1x1x_2x2、..、x_kxk,那么物品x_jxj的花费为b_{x_j}bxj+x_j*kxjk (1<=j<=k)。也就是说,物品的花费等于它的基本花费加上它的编号乘上k。

小白想要在花费不超过SP的情况下买尽量多的物品。注意,一种物品最多买一件。

输入

第一行两个整数,n和SP(1<=n<=10^5105,1<=SP<=10^9109),含义如上。

第二行n个整数b_1b1b_2b2,,,b_nbn (1<=b_ibi<=10^5105).

输出 

将小白最多买的物品数k和买k件物品的最少花费输出到一行

样例输入

3 11
2 3 5

样例输出

2 11

猜你喜欢

转载自blog.csdn.net/qq_41156122/article/details/80329270