codefoces812C-Sagheer and Nubian Market心得

题目描述:

On his trip to Luxor and Aswan, Sagheer went to a Nubian market to buy some souvenirs for his friends and relatives. The market has some strange rules. It contains n different items numbered from 1 to n. The i-th item has base cost ai Egyptian pounds. If Sagheer buys kitems with indices x1,?x2,?...,?xk, then the cost of item xj is axj?+?xj·k for 1?≤?j?≤?k. In other words, the cost of an item is equal to its base cost in addition to its index multiplied by the factor k.

Sagheer wants to buy as many souvenirs as possible without paying more than S Egyptian pounds. Note that he cannot buy a souvenir more than once. If there are many ways to maximize the number of souvenirs, he will choose the way that will minimize the total cost. Can you help him with this task?

输入描述:

The first line contains two integers n and S (1?≤?n?≤?105 and 1?≤?S?≤?109) — the number of souvenirs in the market and Sagheer‘s budget.

The second line contains n space-separated integers a1,?a2,?...,?an (1?≤?ai?≤?105) — the base costs of the souvenirs.

输出描述:

On a single line, print two integers kT — the maximum number of souvenirs Sagheer can buy and the minimum total cost to buy these ksouvenirs.

样例输入1:

3 11

2 3 5

样例输出1:

2 11

样例输入2:

4 100

1 2 5 6

样例输出2:

4 54

样例输入3:

1 7

7

样例输出3:

0 0

题目大意:

你只带了m元钱去市场买东西,市场有n件物品,每一件物品的基本价格为a1,a2,....an,而当你最终决定买k件物品时,每一件物品的价格还得在基本价格上加上i * k元,其中,i为物品的下标,k是可以变得,现在你的任务是,尽量购买多一点物品,当购买物品数量一样的方法有很多的情况下,使花的价格最少。

输入解释:

输入两行。

第一行为两个整数,第一个整数为市场上物品的总数量,第二个整数为你的预算

第二行为这n件物品的基本价格

输出解释:

输出两个证整数,第一个整数为你能购买物品的最大数量,第二个整数为购买这个数量的物品所花的最少价格。

题目分析:

这道题目既然是让我们找最大数量,我们就很容易的想到需要二分答案,而二分的标准是啥?自购买物品的数量,然是数量,我们可以这样想:假设k为我们最终我们购买物品的数量,那么0<=k<=n,我们只需要不断二分k,再在当数量为k的时候去购买价格最低的k件物品,如果预算可以购买这k件物品,就代表这个数量可行,我们保存这个结果,然后从k+1数量到n数量继续二分,否则,我们从0数量到k-1数量二分找可行的数量。分析到这里,思路应该就出来了吧?下面上代码:

#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
const long long  int N = 100001;
long long int a[N],b[N],n,m,sum = 0;
//假设买k件物品
long long int Find(long long int k)
{
    long long int i,j;
    //printf ("购买%lld件物品时:\n",k);
    sum = 0;

//将数量为k时每一件物品的价格保存起来再排序
    for (i = 1; i <= n; i++)
    {
        b[i] = a[i] + i * k;
    }
    sort(b + 1,b + n + 1);

//选择数量为k时价格最小的k件物品购买
    for (i = 1; i <= k; i++)
    {
        //printf ("%lld\n",i);
        sum += b[i];
        //printf ("够买第%lld件物品已经花费%lld元\n",i,sum);

//当购买这k件物品时预算不够了,代表不能购买这么多数量的物品,返回0
        if(sum > m)
        {
            return 0;
        }
    }

//可以购买数量为k的物品,返回1
    return 1;

}
int main(void)
{
    long long int i,j,low,high,mid,mid1,sum1,sum2 = 0;
    scanf ("%lld%lld",&n,&m);
    for (i = 1; i <= n; i++)
    {
        scanf ("%lld",&a[i]);
        //printf ("第%lld件物品价格:%lld\n",i,a[i]);
    }
    low = 0;
    high = n;

//在0-n中二分数量
    while (low <= high)
    {
        mid = low + (high - low) / 2;
        sum1 = Find(mid);

//如果可以购买mid数量的物品,保存mid和sum,然后从mid+1-n二分答案
        if(sum1)
        {
            sum2 = sum;
            mid1 = mid;
            low = mid + 1;
            //printf ("%lld %lld\n",mid1,sum1);
        }

//否则从0-mid-1二分可购买的数量
        else
        {
            //printf ("不能购买%lld件物品\n",mid);
            high = mid - 1;
        }
    }

//输出最终的mid1和sum2
    printf ("%lld %lld\n",mid1,sum2);

return 0;
}

//心得:当涉及到最大或者最小的问题时,我们都应该联想到二分,二分这个算法真的是非常实用的一个算法,在刷二分题目的过程中我也确实对二分有了更加深入的理解。

时间: 2024-08-09 16:48:05

codefoces812C-Sagheer and Nubian Market心得的相关文章

Codeforces Round #417 (Div. 2) C. Sagheer and Nubian Market 二分答案 +排序

Codeforces Round #417 (Div. 2) C. Sagheer and Nubian Market 二分答案 +排序 题意 有 a[ i ] 个数 要求选最多的数 使其和不超过 S ,且在此情况下,和最小选最多数情况下 和最小 且 每个数有加成 如果选了 k个数 那么加成后 就是 a[ i ] + k*i ; 题解 二分mid 表示选了个数 加成一下,将加成以后结果排序一下 , 若前 mid数 和大于 s 则此方案不可行 PS 要用 long long ..... 还有 co

812C - Sagheer and Nubian Market

Sagheer and Nubian Market 二分+排序 比赛时没对,赛后检查才发现check()里的参数类型是int 改成ll就对了.好气哦! 1 #include <bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int N = 1e5+10; 5 ll a[N], b[N], k, t, n, l, r, s, ans; 6 7 bool check(ll x ){ 8 for(int i =

Round #417 C. Sagheer and Nubian Market(Div.2)

On his trip to Luxor and Aswan, Sagheer went to a Nubian market to buy some souvenirs for his friends and relatives. The market has some strange rules. It contains n different items numbered from 1 to n. The i-th item has base cost ai Egyptian pounds

#417 Div2 Problem C Sagheer and Nubian Market (二分 &amp;&amp; std::accumulate)

题意 : 给你 n 件物品和你拥有的钱 S, 接下来给出这 n 件物品的价格, 这些物品的价值不是固定不变的, 价格的变化公式是 a[i]+k*i (i代表第 i 件物品, k 代表你选择买的物品数量, a[i]为物品的底价), 现问你最多能够买多少件物品和所买物品总和, 输出时应该使得所买物品总和尽量小 分析 : 如果我当前能买 k 件物品, 那我肯定能买数量小于 k 的物品, 如果我当前买不起 k 件物品, 那我肯定也不能买比 k 件要多的物品.所以可以考虑二分解法, 在1~n之间二分查找

#417(div2) C. Sagheer and Nubian Market

题意:给出n件商品价格和一个最大限额S,购买时商品的价格变为axj?+?xj·k,xj是下标索引,k是购买数量,求最多能买几件和花费. 思路:二分+排序 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 5 ll a[100005]; 6 ll b[100005]; 7 ll n,s; 8 ll sum; 9 ll check(ll x){ 10 sum=0; 11 for(int i=1;i&

CF812C Sagheer and Nubian Market 二分+贪心

模拟赛给他们出T1好了~ code: #include <bits/stdc++.h> #define ll long long #define N 100006 #define setIO(s) freopen(s".in","r",stdin) using namespace std; int n; ll a[N],ck,A[N],S; int check(int tmp) { int i,cnt=0; for(i=1;i<=n;++i) A[

庄辰超:回顾去哪儿的这些年,最让我骄傲的是收获了这9点管理心得

我前两次的创业 1994 年到 1998 年,我在北大无线电系念书,这是一个纯粹搞科学的专业,但我当时就很喜欢自己写点程序. 我的第一次创业是在大学期间,在大四的时候和同学一起做过一个简单的搜索引擎爬虫软件,获得了 IDG 资本 5 万美金的投资,之后我们开始在北京和上海卖这个软件.当时 Chinabyte 刚进到中国来,没法做一个传统的媒体,同时由于内容的监管只能做 IT 内容,因此我们软件的第一个 copy 就卖给了 Chinabyte,给他们做搜索引擎. 这是我第一次接触互联网.然而当时在

Delphi组件indy 10中IdTCPServer修正及SSL使用心得

indy 10终于随着Delphi2005发布了,不过indy套件在我的印象中总是复杂并且BUG不断,说实话,不是看在他一整套组件的面子上,我还是喜欢VCL原生的Socket组件,简洁,清晰.Indy9发展到了indy10几乎完全不兼容,可叹啊.言归正传.在使用IdTCPServer组件的时候发现了他的漏洞,他的OnConnec,OnExecute,OnDisconnect等事件是在其他线程中执行的,通常情况下这没有问题,但是在特殊的情况下会造成问题,如果其他部分的程序写得有问题就会出现漏洞.

Linux系统理解以及Linux系统学习心得

原创作品转载请注明出处  <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 作者:严哲璟 说一下我对Linux系统的理解 1.加载Linux内核准备:在加载基本输入输出模块(BIOS)之后,从磁盘的引导扇区读入操作系统的代码文件块到内存中,之后开始整个系统的初始化. 2.main.c的start_kernel函数是整个操作系统的入口,这也与Linux是基于C语言的特性相符,start_kernel具体做的动作很多