A.输出简单的Z
知识点:模拟
通过观察图形,不难看出除第一行和最后一行外,其余行均由n - 1个 '.' 和一个 '/' 组成
而第二行 '/'的位置又恰好在n - 1处,第三行在n - 2处,第四行在n - 3处,于是不难推出,第x行的斜杠在n - x + 1处(下标从1开始)
那么,我们可以定义一个二维字符数组,先全部初始化为 '.',遍历从第2行到第 n - 1 行,将其对应下标处的 '.' 修改成 '/'。
然后分开输出首行,中间行和末行即可
(ps:本题为多实例,但题面没有要求每两个实例输出之间用换行隔开,所以千万不要在输出后加换行隔开,别问为什么,问就是WA了)
代码实现如下:
#include <iostream>
#include <cstring>
using namespace std;
const int N = 100;
int n;
char g[N][N];
int main()
{
int t;
scanf("%d",&t);
while(t --)
{
scanf("%d",&n);
memset(g, '.', sizeof g);
for(int i = 1; i < n; i ++) printf("-");
puts(">");
for(int i = 2; i < n; i ++)
{
g[i][n - i + 1] = '/';
for(int j = 1; j <= n; j ++)
{
printf("%c", g[i][j]);
}
puts("");
}
printf("<");
for(int i = 1; i < n; i ++)
{
printf("-");
}
puts("");
// puts(""); 别加这一行,加了就是20分钟
}
return 0;
}
B.失眠就数羊
知识点:简单数位拆分,标记数组(可以不用)
定义w数组存储数字0~9的圈的个数(1, 0, 0, 0, 1, 0, 1, 0, 2, 1)
将a到b之间的每一个数进行数位拆分,求得每个数字各位圈的个数的和(建议函数实现)
将上述函数的返回值相加输出即可
tabris笨不笨我不清楚,我只知道我写这题这题数圈数老半天,给自己都数迷糊了(ps:确实不理解4这个三角为什么也算圈儿)
代码实现如下:
#include <iostream>
using namespace std;
const int N = 100;
int n, q[N];
int w[10] = {1, 0, 0, 0, 1, 0, 1, 0, 2, 1};
int check(int x)
{
int res = 0;
while(x > 0)
{
res += w[x % 10];
x /= 10;
}
return res;
}
int main()
{
int t, a, b;
scanf("%d",&t);
long long ans;
while(t --)
{
scanf("%d %d",&a, &b);
ans = 0;
for(int i = a; i <= b; i ++)
{
ans += check(i);
}
printf("%lld\n", ans);
}
}
C.简单的求和
知识点:前缀和
多次查询区间和,自然要祭出我为数不多会用的算法之一——前缀和 来写(虽然有同学反馈用scanf 枚举求和 也能通过,但大概率是数据不够严谨,小问题,前缀和该学还得学)
所谓前缀和,可以简单理解为高中所学的数列的前 n 项和,那么,这个前缀和有什么用呢?
且看本题,多次查询数列区间和,我们以数据范围的上限来计算一波:
数列最长有1e5项,最多有1e5次询问,每次询问最长需要求长为1e5的区间的和,那么计算之后,得到最大操作次数的数量级为1e10(1e5次操作 * 每次操作的1e5个数相加)
众所周知,当题目给定的时间限制为1s时,最大操作次数的数量级大概在1e8(10的8次方),所以直接去暴力枚举是会TLE(超时)的。
这时候,我们的前缀和就派上用场了:
在读入原数组之后,我们定义一个新的数组(或在原数组上进行操作),使得数组下标为 i 处存储元素为从数组第1项到第 i 项的和,如此便得到了前缀和数组。
当我们需要求闭区间区间 l 到 r 的和时,只需用 前缀和数组的第 r 项(即数列前 r 项的和)减去前缀和数组的第 l - 1项 (即数列前 l - 1项的和),得到的差便是所求。
代码实现如下:
#include <iostream>
using namespace std;
const int N = 2e5 + 20;
int n;
long long q[N], w[N];
int main()
{
int m;
scanf("%d %d",&n,&m);
for(int i = 1; i <= n; i ++)
{
scanf("%lld",&q[i]);
// w[i] = w[i - 1] + q[i]; //以 w 数组作为原数组的前缀和数组
q[i] += q[i - 1]; //在原数组上操作得到前缀和数组
}
while(m --)
{
int x, y;
scanf("%d %d",&x, &y);
// printf("%lld\n", w[y] - w[x - 1]);
printf("%lld\n", q[y] - q[x - 1]);
}
return 0;
}
D.沉迷游戏
知识点:排序(外加一点小思维)
观察题给数据范围,可以发现,至少要玩的游戏数量是一定会大于特别喜欢玩的游戏数量的
于是我们可以将最喜欢玩的游戏视作必须要玩的游戏,在读入它们的编号时直接求得它们耗时的和,并将其耗时归零。
然后将整个数组排序(由于特别喜欢的游戏耗时已经归零,它们一定会在排序后的数组的最前面)
对于排序后的数组,直接求前k项和即可
代码实现如下:
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
const int N = 1010;
int n, q[N];
int main()
{
int m, k, x, w = 0;
scanf("%d %d %d",&n,&m,&k);
for(int i = 1; i <= n; i ++)
{
scanf("%d",&q[i]);
}
while(m --)
{
scanf("%d",&x);
w += q[x];
q[x] = 0;
}
sort(q + 1, q + n + 1);
for(int i = 1; i <= k; i ++)
{
w += q[i];
}
printf("%d", w);
return 0;
}
E.X型不明物体
知识点:贪心
(有一说一,题目中的型应写作“形”,这个型看起来一点都不行)
对于任给n个 'X' 形图案,我们可将其看作两条直线,那么,对于一个平面,没有线时,它是一个完整的区域,有一条线时,它被分为了两部分,有两条线时,为了让划分的区域最多,我们让两条线相交,便可以将平面划分为四部分。
对于平面内任意多的已有直线,我们总有办法将新增直线以不与其他线平行,且不穿过其他线交点的形式加入到平面中,假设原有 x 条直线以这种方式存在在平面中,那么新增直线后,平面内会多出 x + 1 条直线。
于是,对于 n 个'X'形图案,我们可以将其视作 2 * n条直线,并将加入平面的过程其拆分,可得到最终划分区域数量的计算公式:
划分区域数量 = 1 + 1 + 2 + ... + 2 * n - 1 + 2 * n
将从1加到2 * n的部分提取出来,用等差数列前n项和公式替换,便得到 1 + n * (n + 1) / 2
代码实现如下:
#include <iostream>
using namespace std;
long long n;
int main()
{
scanf("%lld", &n);
n *= 2;
printf("%lld", n * (n + 1) / 2 + 1);
return 0;
}
F.迷失的他
知识点:BFS
时间不太够,废话待会儿再添,先上代码
代码实现如下:
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
const int N = 100;
typedef pair<int, int> PII;
int n, m, ans, cnt = 10000, w[N][N];
char g[N][N];
void bfs(int a, int b)
{
queue<PII> q;
q.push({a, b});
w[a][b] = 0;
int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0};
while(!q.empty())
{
PII t = q.front();
q.pop();
if(g[t.first][t.second] == 'e')
{
ans ++;
cnt = min(w[t.first][t.second], cnt);
continue;
}
for(int i = 0; i < 4; i ++)
{
int x = t.first + dx[i], y = t.second + dy[i];
if(x > 0 && x <= n && y > 0 && y <= m && w[x][y] == -1 && g[x][y] != '*')
{
w[x][y] = w[t.first][t.second] + 1;
q.push({x, y});
}
}
}
}
int main()
{
int x, y;
scanf("%d %d\n",&n,&m);
for(int i = 1; i <= n; i ++)
{
for(int j = 1; j <= m; j ++)
{
scanf("%c",&g[i][j]);
if(g[i][j] == 'k')
{
x = i;
y = j;
}
}
getchar();
}
memset(w, -1, sizeof(w));
bfs(x, y);
if(ans) printf("%d %d", ans, cnt);
else puts("-1");
return 0;
}