这里写目录标题
- A. [Yet Another Two Intergers Problem](https://codeforces.ml/contest/1409/problem/A)
- [B.Minimum Product](https://codeforces.ml/contest/1409/problem/B)
- [C. Yet Another Array Restoration](https://codeforces.ml/contest/1409/problem/C)
- [D.Decrease the sum of Digits](https://codeforces.ml/contest/1409/problem/D)
- [E.Two Platforms](https://codeforces.ml/contest/1409/problem/E)
A. Yet Another Two Intergers Problem
题目大意:
给定两个整数a,b,每次可以把a变成a+k或a-k(k∈[1,10]),求需要多少次操作可以把a变成b。
思路:
每次都加或减10,看看b-a的值能否整除10不能整除则将商加一,否则输出商。
#include<iostream>
#include <algorithm>
#include<cmath>
using namespace std;
int main() {
int t;
scanf("%d", &t);
while (t--)
{
long long a, b;
scanf("%lld%lld", &a, &b);
if (a == b) {
printf("0\n");
}
else {
printf("%lld\n", abs((b - a)) / 10 + (abs((b - a)) % 10 == 0 ? 0 : 1));
}
}
}
B.Minimum Product
题目大意:
给定a,b,x,y,n,你可以进行至多n次操作,每次操作把a或b减一,但必须保证a≥x与b≥y始终成立,求ab的最小值。
思路:
由数学知识可知,当两个数相差越大时,其乘积越小。我们分别对两个数进行操作,取最小值即可。
#include<iostream>
using namespace std;
typedef long long ll;
ll a, b, x, y, n;
ll res(ll a, ll b, ll x, ll y, ll m) {
if (a - x >= m)a -= m, m = 0;
else m -= (a - x), a = x;
if (b - y >= m) b -= m, m = 0;
else m -= (b - y), b = y;
return a * b;
}
int main() {
int t;
cin >> t;
while (t--)
{
cin >> a >> b >> x >> y >> n;
cout << min(res(a,b,x,y,n), res(b,a,y,x,n)) << endl;
}
}
C. Yet Another Array Restoration
题目大意:
给定两个数a,b,和长度n构造一个长度为n的等差数列,其中数列中包含这两个数,且使得整个数组的所有元素之和最小。
思路:
因为将答案看作为一个等差数组,所以我们从1 开始枚举公差一直枚举到b - a。分别判断在当前这个公差下,ab之间的数以及1a之间的数以及b~正无穷直接的所有个数能否等于n即可。
#include<iostream>
#include<algorithm>
using namespace std;
int main() {
int t;
cin >> t;
while (t--)
{
int n, x, y;
cin >> n >> x >> y;
int flag = y - x;
int ans = 0;
for (int i = 1; i <= flag; i++) {
int mid = 0;
if (flag % i == 0&&(flag / i) + 1 <= n) {
mid = (flag / i) + 1;
int f = 0;
flag = x;
while (mid < n) {
flag -= i;
if (x > 0)
mid++;
else {
break;
}
}
flag = x;
while (mid < n) {
flag += i;
mid++;
}
if (mid == n) {
ans = i;
break;
}
}
}
int hh = 2;
cout << x <<' '<<y;
for (int i = x+ans; i < y; i += ans)
{
cout << ' '<< i;
++hh;
}
for (int i = x - ans; hh < n&&i>0; i -= ans)
{
cout << ' '<< i;
++hh;
}
for (int i = y + ans; hh < n; i += ans)
{
cout << ' ' << i;
++hh;
}
cout << endl;
}
}
D.Decrease the sum of Digits
题目大意:
给定一个数字,可以对其进行+1的操作,判断最少进行几次操作,可以使得它每一位上的数字之和小于等于s。
思路:
我们通过样例发现啊,这个最终得到的数一定是一个xxx……0000,所以我们从这个数的末尾开始算起,每次都让一位变成0并且向前进一,每次进行操作后判断所有位之和,相等时输出这个数与初始数之差即可
#include<iostream>
#include<algorithm>
using namespace std;
typedef unsigned long long ll;
ll sum(ll x) {
ll ans = 0;
while (x > 0)
{
ans += x % 10;
x /= 10;
}
return ans;
}
int main() {
int t;
cin >> t;
while (t--)
{
ll n, s;
cin >> n >> s;
if (sum(n) <= s) {
cout << 0 << endl;
continue;
}
else {
ll nn = n, a = 10;
while (sum (nn) > s)
{
nn += a - nn % a;
a *= 10;
}
cout << nn - n << endl;
}
}
}
E.Two Platforms
题目大意:
给出平面上 n个点,第 i 个点为 (xi, yi)定义一个平台为与 x轴平行的一条长度为 k 的线段。你有两个平台,并且可以选择每个平台的放置位置。确定平台位置之后,平面上的点会下落(即:点的 y 坐标开始减小),当这个点落在遇到某一个平台 时,就停止下落。如果这个点始终没能遇到一个 平台,那么这个点就丢失 了。求一种放置 平台 的方法,最大化平台能“接住”的点。输出最大的接住点的个数。
思路:
首先我们发现,整个问题,与点的y坐标无关,所以我们对问题就进行了简化,对其x坐标进行排序,我们以每个点都为平台的起点,通过二分来查找解的数量,由于是两个平台,所以我们可以提前处理出来一个数组,这个数组存储的是从第i个点到第n个点范围内的最优解数量。(其实可以两个都预处理出来,最后相加取最大值)。之所以这样做是因为在判断完第一块平台后我们无法得出后面的点那个点的解最多,而这样就可以将问题解决了。
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 200010;
typedef long long ll;
ll a[N], b[N];
ll hou[N];
int main() {
int t;
scanf("%d", &t);
while (t--)
{
memset(hou, 0, sizeof hou);
int n, k;
scanf("%d %d", &n, &k);
for (int i = 1; i <= n; i++)scanf("%lld", &a[i]);
for (int i = 1; i <= n; i++)scanf("%lld", &b[i]);
sort(a + 1, a + 1 + n);
for (int i = n; i >= 1; i--) {
ll hh = a[i] + k;//从a[i]开始可以覆盖到的最远的地方
ll ii = upper_bound(a + 1, a + 1 + n, hh) - a;
hou[i] = max(hou[i + 1], ii - i);//取max,因为数组hou[i]的含义是从[i,n]任选一个小球开始覆盖的最优值
}
ll ans = 0;
for (int i = 1; i <= n; i++) {
ll hh = a[i] + k;
ll ii = upper_bound(a + 1, a + 1 + n, hh) - a;
ans = max( ans, hou[ii]+ (ii - i));
}
printf("%lld\n", ans);
}
}
第二篇div. 3题解!!
正正加油!!!