Codeforces J. Sagheer and Nubian Market(二分枚举)
题目描述:
Sagheer and Nubian Market
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
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 \(a_i\) Egyptian pounds. If Sagheer buys k items with indices x1, x2, ..., \(x_k\), then the cost of item x**j is \(a_{x_j}\) + \(x_j\)·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?
Input
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, ..., a**n (1 ≤ a**i ≤ 105) — the base costs of the souvenirs.
Output
On a single line, print two integers k, T — the maximum number of souvenirs Sagheer can buy and the minimum total cost to buy these k souvenirs.
Examples
Input
Copy
3 112 3 5
Output
Copy
2 11
Input
Copy
4 1001 2 5 6
Output
Copy
4 54
Input
Copy
1 77
Output
Copy
0 0
Note
In the first example, he cannot take the three items because they will cost him [5, 9, 14] with total cost 28. If he decides to take only two items, then the costs will be [4, 7, 11]. So he can afford the first and second items.
In the second example, he can buy all items as they will cost him [5, 10, 17, 22].
In the third example, there is only one souvenir in the market which will cost him 8 pounds, so he cannot buy it.
思路:
题目是说现在有S块钱,有N个物品,物品的价格是本价加上购买的物品数乘物品编号,每个物品只能买一次。求S最多能买多少个物品,如果在买的数量相同的情况下求出用钱最少的。
刚开始,一看n是\(10^5\)量级,可以枚举来做,从n到0,每次枚举都算一下每件物品的花费,为了买到的物品最多的情况下花费要尽可能少,给每样物品的花费排一个序,再求一个花费前缀和,再用lower_bound二分查找大于S的值的位置,减一就是小于等于S的花费的位置记为pos。
下面详细说一说pos的含义:如果找到了一个位置pos(这里是前缀和,位置实际上就是购买的物品数目)花费小于等于S,这个位置pos表示了在资金足够的情况下,在枚举的物品数i的限制下,最多可以买pos个物品。如果pos等于i,就刚刚好是可以购买的最大物品数。如果pos>i,因为现在可能还没用完S,就说明有可能买更多的物品(同时买更多的物品时每个物品的花费要高些),如果pos<i,就说明现在资金用到最大程度都买不到i个物品,说明i不满足条件,继续往下枚举。(这是当时意识不太清醒时想出来的,现在来看竟然感觉不是很好理解,佩服我自己)。
由于i是从大到小枚举的,那pos>i的状态表示的购买更多物品的可能性已经枚举过了,现在只有两种可能,就是当前枚举值满足和不满足。一旦出现满足,跳出循环,输出答案。这种方法的时间复杂度是\(O(n^2log_2n)\)的,过不了太多数据。
代码:
#include <iostream>
#include <algorithm>
#include <memory.h>
#include <cstdio>
#define max_n 100005
#define INF 0x3f3f3f3f
using namespace std;
int n;
int S;
int a[max_n];
long long sum[max_n];
template<typename T>
inline void read(T& x)
{
x=0;int f=0;char ch=getchar();
while('0'>ch||ch>'9'){if(ch=='-')f=1;ch=getchar();}
while('0'<=ch&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
x=f?-x:x;
}
#pragma optimize(2)
int main()
{
read(n);
read(S);
int minm = INF;
for(int i = 1;i<=n;i++)
{
read(a[i]);
minm = min(minm,a[i]);
}
int items = S/minm;//降一下枚举的起点
items = min(items,n);
long long money = 0;
int pos = 0;
for(int i = items;i>0;i--)
{
memset(sum,0,sizeof(sum));
for(int j = 1;j<=n;j++)
{
sum[j] = a[j] + i*j;//求花费
}
sort(sum+1,sum+n+1);
/*for(int j = 1;j<=n;j++)
{
cout << sum[j] << " ";
}
cout << endl;*/
for(int j = 1;j<=n;j++)
{
sum[j] += sum[j-1];//求花费的前缀和
}
/*for(int j = 1;j<=n;j++)
{
cout << sum[j] << " ";
}
cout << endl;
cout << endl;*/
pos = upper_bound(sum+1,sum+n+1,S)-sum-1;
//cout << "pos " << pos << endl;
if(pos>=i)
{
if(pos<=n)//这里是所有元素都小于S时的情况
{
money = sum[pos];
}
else
{
money = sum[pos-1];
}
break;
}
}
printf("%d %I64d\n",pos,money);
return 0;
}
其实枚举是对的,不过不是线性枚举,采用二分枚举,复杂度降到\(O(log_2(nlog_2n))\)。
注意返回的是记录下的最后的满足条件的枚举的物品数量。
代码:
#include <iostream>
#include <algorithm>
#define max_n 100005
using namespace std;
int n;
int S;
int a[max_n];
long long sum[max_n];
long long cost = 0;
long long mincost = 0;
int items = 0;
template<typename T>
inline void read(T& x)
{
x=0;int f=0;char ch=getchar();
while('0'>ch||ch>'9'){if(ch=='-')f=1;ch=getchar();}
while('0'<=ch&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
x=f?-x:x;
}
#pragma optimize(2)
int main()
{
read(n);
read(S);
for(int i = 1;i<=n;i++)
{
read(a[i]);
}
int l = 0;
int r = n;
int mid = 0;
while(l<=r)
{
//cout << "l " << l << " r " << r << endl;
cost = 0;
mid = (l+r)>>1;
//cout << "mid " << mid << endl;
for(int i = 1;i<=n;i++)
{
sum[i] = (long long)a[i]+(long long)mid*i;
}
sort(sum+1,sum+n+1);
for(int i = 1;i<=mid;i++)
{
cost += sum[i];
}
//cout << "cost " << cost << endl;
if(S>=cost)
{
items = mid;
mincost = cost;
l=mid+1;
}
else
{
r=mid-1;
}
}
printf("%d %I64d",items,mincost);
return 0;
}
Codeforces J. Sagheer and Nubian Market(二分枚举)的更多相关文章
- CodeForces - 812C Sagheer and Nubian Market 二分
On his trip to Luxor and Aswan, Sagheer went to a Nubian market to buy some souvenirs for his friend ...
- CodeForce-812C Sagheer and Nubian Market(二分)
Sagheer and Nubian Market CodeForces - 812C 题意:n个货物,每个货物基础价格是ai. 当你一共购买k个货物时,每个货物的价格为a[i]+k*i. 每个货物只 ...
- 【贪心+二分】codeforces C. Sagheer and Nubian Market
http://codeforces.com/contest/812/problem/C [题意] 如何花最少的钱买最多的纪念品?首要满足纪念品尽可能多,纪念品数量一样花钱要最少,输出纪念品数量以及最少 ...
- #417 Div2 Problem C Sagheer and Nubian Market (二分 && std::accumulate)
题目链接 : http://codeforces.com/problemset/problem/812/C 题意 : 给你 n 件物品和你拥有的钱 S, 接下来给出这 n 件物品的价格, 这些物品的价 ...
- CF812C Sagheer and Nubian Market 二分+贪心
模拟赛给他们出T1好了~ code: #include <bits/stdc++.h> #define ll long long #define N 100006 #define setI ...
- Codeforces Round #417 C. Sagheer and Nubian Market
C. Sagheer and Nubian Market time limit per test 2 seconds memory limit per test 256 megabytes O ...
- AC日记——Sagheer and Nubian Market codeforces 812c
C - Sagheer and Nubian Market 思路: 二分: 代码: #include <bits/stdc++.h> using namespace std; #defin ...
- CF812C Sagheer and Nubian Market
CF812C Sagheer and Nubian Market 洛谷评测传送门 题目描述 On his trip to Luxor and Aswan, Sagheer went to a Nubi ...
- Codeforces812C Sagheer and Nubian Market 2017-06-02 20:39 153人阅读 评论(0) 收藏
C. Sagheer and Nubian Market time limit per test 2 seconds memory limit per test 256 megabytes input ...
随机推荐
- Linux进程和计划任务管理
1.笔记: 去掉头部:ps -aux - - no -heade 默认信号:15 强制:9 在命令前些一个nohup不再占用终端 date -s:修改时间 ntpdate pool.ntp.org:同 ...
- [LeetCode] 491. Increasing Subsequences 递增子序列
Given an integer array, your task is to find all the different possible increasing subsequences of t ...
- oracle--dump 块与块分析 (dump 深入实践二)
一,建立测试环境 01,一个oracle数据库环境 02,具体数据库实验环境配置 SQL> create user test1 identified by kingle; User create ...
- C# HTTP系列6 HttpWebResponse.StatusCode 响应代码中文详解
系列目录 [已更新最新开发文章,点击查看详细] 1xx - 信息提示 这些状态代码表示临时的响应.客户端在收到常规响应之前,应准备接收一个或多个 1xx 响应 · 100 - Continue ...
- Gitlab CI/CD
Gitlab CI/CD 前言 纵观人类历史的发展以及三次工业革命,你会发现利用机器来替代部分人力劳动,将重复的工作自动化从而解放生产力都是发展的必然趋势,在软件工程领域也不例外,其中 CI/CD 就 ...
- Vue.js 源码分析(十二) 基础篇 组件详解
组件是可复用的Vue实例,一个组件本质上是一个拥有预定义选项的一个Vue实例,组件和组件之间通过一些属性进行联系. 组件有两种注册方式,分别是全局注册和局部注册,前者通过Vue.component() ...
- [转帖]linux lsof 用法简介
linux lsof 用法简介 https://www.cnblogs.com/saneri/p/5333333.html 1.简介: lsof(list open files)是一个列出当前系统打开 ...
- 很好的OpenCV入门资料
https://files.cnblogs.com/files/mqingqing123/OpenCV%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B.rar
- Spring+Mybatis动态切换数据源
功能需求是公司要做一个大的运营平台: 1.运营平台有自身的数据库,维护用户.角色.菜单.部分以及权限等基本功能. 2.运营平台还需要提供其他不同服务(服务A,服务B)的后台运营,服务A.服务B的数据库 ...
- HBase统计表行数(RowCount)的四种方法
背景:对于其他数据存储系统来说,统计表的行数是再基本不过的操作了,一般实现都非常简单:但对于HBase这种key-value存储结构的列式数据库,统计 RowCount 的方法却有好几种不同的花样,并 ...