B : 截绳子
题目描述
有 n 段绳子,长短不一。现在要从中截出 k 段长度相同的绳子。当然,一段绳子可以截出来多段绳子。截出来的绳子最长是多少?
输入格式
第一行两个整数 n 和 k (1≤n,k≤105)
接下来 n 行,每行有一个整数 ai (1≤ai≤107),代表每根绳子的长度
输出格式
一个数,代表最长长度。相对误差或绝对误差不超过 10−6
测试样例
样例 1
输入:
4 11 802 743 457 539
输出:
200.5
解答
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n, k;
cin >> n >> k;
double a[n];
double f = 0;
double t = 100000000;
// 输入每段绳子的长度,并找到最短的那一根
for (int i = 0; i < n; i++)
{
cin >> a[i];
f = f + a[i];
if (a[i] < t)
{
t = a[i];
}
}
double d1 = 0, d2 = 0;
double h = 0;
// 二分法的起点与终点设置
d1 = t / k; // 最短时为最短绳子一根就可以得到k根绳子
d2 = f / k; // 最长时为全部绳子合在一起,剪出k根绳子的长度
int g1 = 0;
while (1)
{
h = (d1 + d2) / 2;
int u = 0;
// 假设截取h长度,计算可以获得多少根绳子
for (int i = 0; i < n; i++)
{
u = a[i] / h;
g1 = g1 + u;
}
// h太大时,g1会小于k
if (g1 < k)
{
d2 = h;
}
else if (g1 >= k)
{
d1 = h;
}
g1 = 0;
// 判断若分界线处小于1e-6时,输出d1即可
if ((d2 - d1) <= 1e-6)
{
break;
}
}
cout << d1 << endl;
return 0;
}
C : 复印机
题目描述
有一份原稿,需要复印出 n 份复印件出来。有两台复印机,一台可以每 x 秒复印出一份,另一台可以每 y 秒复印出一份。现在想知道,至少需要多久才能复印完成?
提示:复印件也可以被复印
输入格式
一行三个整数 n,x 和 y (1≤n≤2×108,1≤x,y≤10)
输出格式
一个整数,代表复印 n 份的最短时间
测试样例
样例 1
输入:
4 1 1
输出:
3
样例 2
输入:
5 1 2
输出:
4
解答
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n, x, y;
cin >> n >> x >> y;
int sum = min(x, y);
int d1 = (n - 1) * min(x, y);
int d2 = (n - 1) / (x + y);
while (1)
{
int s = (d1 + d2) / 2;
if (s == d2)
{
break;
}
int f = s / x + s / y;
if (f < n - 1)
{
d2 = s;
}
else if (f >= n - 1)
{
d1 = s;
}
}
cout << d1 + sum << endl;
return 0;
}
D : 商店
题目描述
一条街上有 n 个商店,在第 i 个商店,可以以 ai 的价格买入一个商品,也可以以 ai 的价格卖出一个商品。商品很沉,最多只能同时拿着 1 个商品在街上走。现在按照给定顺序依次访问所有商店,那么,最大收益是多少?在获得最大收益的前提下,最少交易次数是多少?
输入格式
第一行一个整数 T (1≤T≤5),代表测试用例个数
下面 T 组数据,其中每一组数据都占两行,其中
第一行一个整数 n (1≤n≤105),代表商店个数
下面一行 n 个整数,其中第 i 个数为 ai (0≤ai<2147483648),代表在第 i 个商店可以买入或卖出商品的价格
输出格式
对于每个例子,输出一行两个整数,分别代表最大收益和获得最大收益的前提下最少的交易次数
测试样例
样例 1
输入:
1 5 9 10 7 6 8
输出:
3 4
解答
#include <bits/stdc++.h>
using namespace std;
int main()
{
int T;
cin >> T; // T次循环
for (int i = 0; i < T; i++)
{
int n;
cin >> n; // n个商店
int a[n]; // 每一个商店的价格
int b[n]; // 判断是否卖出
long long x = 0; // 价值
int d = 0; // 次数
// 输入每一个商店的价格,并初始化
for (int j = 0; j < n; j++)
{
cin >> a[j];
b[j] = 0;
}
// 寻找每一个卖出点,将其标记
for (int j = 0; j < n - 1; j++)
{
if (a[j] > a[j + 1])
{
b[j] = 1;
}
}
b[n - 1] = 1; // 最后一个商店进行标记
int w = a[0]; // w是买
for (int j = 0; j < n; j++)
{
if (b[j] == 1) // 如果有标记,进行卖出
{
long long h = x;
x = x + a[j] - w; // 利润计算
if (h != x)
// 判断是否有利润的改变,如果没有,相当于没有交易(在该商店买了商品,又马上卖掉)
{
d = d + 2;
}
if (j == n - 1)
{
break;
}
else
{
w = a[j + 1]; // 在这个地点买入
}
}
}
cout << x << " " << d << endl;
}
return 0;
}
E : 游戏
题目描述
Alice 和 Bob 在做游戏。Alice 写下了 n 个不同的数字,又选取了数字 K。Alice 让 Bob 进行一些操作,每次操作如下:
- 选取两个整数 x,y ,它们的差值不超过 K ,即 ∣x−y∣<=K
- 删除它们中较小的数字
Bob 的任务是,尽可能多的进行这样的操作。当然 Bob 有可能一次操作都做不了。那么,Bob 最多可以进行多少次操作?
输入格式
第一行两个整数 n,K (1≤n≤105,1≤K≤1012)
下面一行 n 个整数,其中第 i 个数为 ai (0≤ai≤1012),代表 Alice 写下的数字
输出格式
输出一个整数,代表 Bob 最多可以进行的操作次数
测试样例
样例 1
输入:
5 1 3 7 4 1 5
输出:
2
解答
#include <bits/stdc++.h>
using namespace std;
int main()
{
long long n, K;
cin >> n >> K;
long long a[n];
int sum = 0;
for (int i = 0; i < n; i++)
{
cin >> a[i];
}
sort(a, a + n);
if (n == 1)
{
cout << sum << endl;
}
else
{
for (int i = 0; i < n - 1; i++)
{
if ((a[i + 1] - a[i]) <= K)
{
sum++;
}
}
cout << sum << endl;
}
return 0;
}