本场题目难度较上场有所增加,思维量较大,但是涉及的知识点都已经提及(都可写。
难度指数:3
这题我本来想放在上一场当防AK题,但是
觉得太简单了又放这场当篇难题了。
解题思路:首先简化问题,如果没有单人皮划艇,显然是将所有人按体重排序,从前往后两两结合最优。题目多了两个单人皮划艇,相等于可以去除两个人,数据范围非常小,只需枚举这两个人即可。
新知识点:
AC代码:
#include <bits/stdc++.h>
using namespace std;
int n, a[110];
int main()
{
while (~scanf("%d", &n))
{
n *= 2;
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
sort(a + 1, a + 1 + n);
int ans = 0x3f3f3f3f;
for (int i1 = 1; i1 <= n; i1++)
for (int i2 = i1 + 1; i2 <= n; i2++)
{
int sum = 0, ff = 0, fir = 0;
for (int i = 1; i <= n; i++)
{
if (i == i1 || i == i2)
continue;
ff++; //ff的奇/偶表示这是双人皮划艇上的前/后一个人
if (ff % 2 == 0)
sum += a[i] - fir;
else
fir = a[i];
}
ans = min(ans, sum); //取最小方案
}
printf("%d\n", ans);
}
return 0;
}
难度指数:3
解题思路:事实上,只有字符R、起点、终点才是我们会落脚的地方。我们要从起点经过若干个字符R到达终点,那么只需计算每个落脚点之间的距离 D I S i DIS_i DISi,使用最大的 D I S k DIS_k DISk作为第一次跳跃的距离就可以到达终点。
AC代码:
#include <bits/stdc++.h>
using namespace std;
char s[100010];
int main()
{
int t;
for (scanf("%d", &t); t; t--)
{
scanf("%s", s + 1);
int len = strlen(s + 1);
int ans = 0, pre = 0;
for (int i = 1; i <= len; i++)
if (s[i] == 'R')
{
ans = max(ans, i - pre);
pre = i;
}
ans = max(len + 1 - pre, ans);
printf("%d\n", ans);
}
return 0;
}
难度指数:1.001
看没人写出来的份上加个0.001
解题思路:刚开始第 i i i糖果有 i i i颗糖,第 j j j次你可以选择一袋糖果,在其他糖果袋中加入 j j j颗糖。
ps:多种解要求字典序最小,可观察样例,初始时有1 、2两袋糖果,此时有两种解法:
第一种
1
2
第二种
2
1 2
第二种的12字典序小于2。
综上所述,显然只需要输出
n
1 2 3 ... n
即可。
新知识点:
AC代码:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int t;
for (scanf("%d", &t); t; t--)
{
int n;
scanf("%d", &n);
printf("%d\n", n);
for (int i = 1; i < n; i++)
printf("%d ", i);
printf("%d\n", n); //控制行末空格
}
return 0;
}
难度指数:4.5
构造题,一般来说这种题都会有一种通解,也就是按某种规律构造,解决这种问题,我们只需找到构造通解的规律即可。
解题思路:找规律。观察第二个样例。前三个数是1到n,后三个数也是1到n的排列,我们可以大胆猜想,只需2n的数就可以构造出正确答案,并且前n个数是1到n。对于后三个数132则可以有很多猜想。
例如:
1 n 2 n-1 3 n-2
1 3 5 7... 2 4 6 8...
验证一下n=5,使用猜想二构造时答案正确,并且这种构造字典序十分小,这时候就可以交一发加以验证。
AC代码:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++)
printf("%d ", i);
for (int i = 1; i <= n; i += 2)
printf("%d ", i);
for (int i = 2; i <= n; i += 2)
printf("%d ", i);
return 0;
}
难度指数:2.5
没什么好说的,模拟题,注意细节即可。
AC代码:
#include <bits/stdc++.h>
using namespace std;
char a[110];
int main()
{
int t;
scanf("%d", &t);
while (t--)
{
scanf("%s", a);
int len = strlen(a), sum = 0, res = 0, ff = 0;
for (int i = 0; i <= len; i++) //这里要枚举i到len,因为可能以数字结尾
{
if (a[i] >= '0' && a[i] <= '9' && !ff) //如果是第一个数字
{
res = a[i] - '0';
ff = 1;
}
else if (a[i] >= '0' && a[i] <= '9' && ff) //如果是数字但不是第一个
{
res = res * 10 + a[i] - '0';
}
else //不是数字
ff = 0, sum += res, res = 0;
}
printf("%d\n", sum);
}
return 0;
}
难度指数:2
结构体水题。
AC代码:
#include <bits/stdc++.h>
using namespace std;
struct student
{
int num, c, m, e, s;
} s[310];
bool cmp(student a, student b)
{
if (a.s == b.s)
{
if (a.c == b.c)
{
return a.num < b.num;
}
return a.c > b.c;
}
return a.s > b.s;
}
int main()
{
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
scanf("%d %d %d", &s[i].c, &s[i].m, &s[i].e);
s[i].num = i;
s[i].s = s[i].c + s[i].m + s[i].e;
}
sort(s + 1, s + 1 + n, cmp);
for (int i = 1; i <= 5; i++)
printf("%d %d\n", s[i].num, s[i].s);
return 0;
}
难度指数:4.7
预处理出答案,最后O1(一次性)查询
新知识点:三维数组
AC代码:
#include <iostream>
using namespace std;
int MONTH[15] = {0, 31, -1, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
void GetFebruary(int y)//闰年 二月份29天 平年28天
{
if (y % 400 == 0 || (y % 4 == 0 && y % 100))
MONTH[2] = 29;
else
MONTH[2] = 28;
}
int y = 1900, m = 1, d = 1, nd;
int y2 = 2020, m2 = 12, d2 = 13;
int sum[2030][13][33];//sum[i][j][k]表示i年j月k日开始总共还可以跑多少天
void pre()
{
int week = 0;
while (y2 != y || m2 != m || d2 != d)
{
int prey2 = y2, prem2 = m2, pred2 = d2;
GetFebruary(y2);
--d2, week = (week + 1) % 7;
if (d2 == 0)
{
--m2;
if (m2 == 0)
{
m2 = 12;
--y2;
}
d2 = MONTH[m2];
}
sum[y2][m2][d2] = sum[prey2][prem2][pred2];
if (week != 0 && week != 1)
sum[y2][m2][d2]++;
}
}
int main()
{
pre(); //预处理
while (~scanf("%d-%d-%d %d", &y, &m, &d, &nd) && nd)
{
printf("%s", (sum[y][m][d] >= nd ? "huahua yyds\n" : "~~~>_<~~~\n"));
}
return 0;
}
难度指数:0.00001
无 fa ke 说
AC代码:
#include <iostream>
using namespace std;
int main()
{
int n;
for (scanf("%d", &n); n; n--)
printf("I will make a progress!!!\n");
return 0;
}
难度指数:4.4
平局和输都算赢。
AC代码:
#include <iostream>
using namespace std;
int main()
{
int n, x, y, z, a, b, c;
scanf("%d%d%d%d%d%d%d", &n, &x, &y, &z, &a, &b, &c);
int ans1 = n - min(x, a + c) - min(y, b + a) - min(z, b + c);
int ans2 = min(x, b) + min(y, c) + min(z, a);
printf("%d %d\n", ans1, ans2);
return 0;
}
难度指数:2.8
三重枚举会时间超限,枚举 i 、 j i、j i、j,第三个数就是 n − i − j n-i-j n−i−j。
AC代码:
#include <bits/stdc++.h>
using namespace std;
bool f(long long x) //判断素数
{
if (x <= 1)
return 0;
for (long long i = 2; i * i <= x; i++)
if (x % i == 0)
return 0;
return 1;
}
int main()
{
long long n;
cin >> n;
for (int i = 2; i <= n; i++)
if (f(i))
for (int j = 2; i + j <= n - 2; j++)
if (f(j) && f(n - i - j))
return printf("%d %d %d\n", i, j, n - i - j), 0;
return 0;
}