首页 > 其他分享 >Criss Cross OJ【R001】8月月赛I题解合集

Criss Cross OJ【R001】8月月赛I题解合集

时间:2022-10-10 18:35:57浏览次数:91  
标签:10 return OJ Criss int 题解 sum ++ mathrm

R0011. 「T1」积木高塔 Solution

返回题目

简要题意:

给定一个矩阵,以及其每一格中完全相同立方体的高度(即个数),求:

  1. 这座高塔最高点的高度。

  2. 这座高塔从第 \(1\) 层到最高层之间,每一层的立方体个数。

题目分析:

做法 \(1\):

期望得分:\(50\ pts\)

对于层数,我们可以在读入时使用 max 函数取得最高层,也就是求出了总层数。然后对于每一层,都扫描一遍,如果积木柱高度大于等于这一层的高度,就说明这个积木柱在这个层数有一格积木,故 cnt++

时间复杂度:\(\mathcal{O}(nmk)\)

$ \mathrm{Code:} $

//Code by Polarie,略有修改
#include <bits/stdc++.h>
using namespace std;
int a[10001][10001];

int main () {
	int n, m, maxn = 0;
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			cin >> a[i][j];
			maxn = max(maxn, a[i][j]);//取最大值
		}
	}
	cout << maxn << endl;
	for (int i = 1; i <= maxn; i++) {
		int cnt = 0;//归零
		for (int j = 1; j <= n; j++) {
			for (int k = 1; k <= m; k++) {
				if (a[j][k] >= i)
					cnt++;//扫描
			}
		}
		cout << cnt << endl;
	}
	return 0;//好习惯
}

然鹅 \(\mathrm{Subtask\ 3}\) 全部 \(\mathrm{TLE}\)……

做法 \(2\):

期望得分:\(100\ pts\)

既然要统计积木个数,那我们就考虑计数排序,利用了桶排的思想,这样的好处是不用扫描,且不用存储矩阵,即少开了一个 \(5000 \times 5000\) 的二维数组。

时间复杂度:\(\mathcal{O}(nm)\)

$ \mathrm{Code:}$

//Code by __er
#include <bits/stdc++.h>
using namespace std;
int maxn = -1, n, m, i, j, ans[11]/*桶*/, tmp;

inline int read() {//快速读入
	int x = 0, f = 1;
	char ch = getchar();
	while (ch < '0' || ch > '9') {
		if (ch == '-')
			f = -1;
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9')
		x = x * 10 + ch - '0', ch = getchar();
	return x * f;
}

int main() {
	n = read();
	m = read();
	int nm = n * m;
	ans[1] = nm;//所有积木柱高度都大于1,故第一层必然全都有
	for (i = 1; i <= nm; i++) {
		tmp = read();
		maxn = max(maxn, tmp);
		while (tmp >= 2) {
			ans[tmp]++;
			tmp--;//统计
		}
	}
	cout << maxn << endl;
	for (i = 1; i <= maxn; i++) {
		cout << ans[i] << endl;
	}
	return 0;
}

不开 \(O2\) 最慢一个点也在 \(600ms\) 以下,足以通过此题。

R0012. 「T2」回文质数 Solution

返回题目

简要题意:

给定一个区间的左边界和右边界,输出其中所有既是回文数也是质数的数。

题目分析:

先思考做法:

  1. 暴力枚举 \([l,r]\) 的每一个数。

数据范围 \(1\) 的后面有 \(8\) 个 \(0\) 啊,好好想想你在做什么。

  1. 因为判断回文数较快且回文数较少,所以先判断回文数,再判断质数。

看起来比较合理了吧,但是复杂度 \(\mathcal{O}(\sum_{i=l}^{r} \dfrac{i}{2}+\sqrt{i})\),或者说简单点:\(\mathrm{TLE}\)。

所以我们采用更快的方法,生成回文质数:

int reverse(int n) {
	int a[10], i, sum = 0, t = n;
	for (i = 0; n > 0; i++, n /= 10) {
		a[i] = n % 10;
	}
	for (int j = 1; j < i; j++) {
		sum = sum * 10 + a[j];
	}
	return sum + t * pow(10, i - 1);
}

bool prime(int n) {
	if (n == 1) {
		return false;
	}
	if (n == 2) {
		return true;
	}
	if (n % 3 == 0) {
		return false;
	}
	for (int i = 7; i * i <= n; i++) {
		if (n % i == 0) {
			return false;
		}
	}
	return true;
}
void dfs(int i) {
	int x = reverse(i);
	if (x > r) {
		return;
	}
	if (prime(x) && x != 7 && x >= l) {
		a[sum++] = x;
	}
	for (int j = 0; j < 10; j++) {
		if (i * i < r) {
			dfs(i * 10 + j);
		} else {
			return;
		}
	}
}

但是,你会惊讶的发现,这么写是会 \(\mathrm{WA}\) 滴!

因为它是无序生成的,所以要排序,这里用的是二分快排:

void qsort(int l, int r) {
	int i = l, j = r, mid = a[(l + r) / 2];
	while (i <= j) {
		while (a[i] < mid)
			i++;
		while (a[j] > mid)
			j--;
		if (i <= j)
			swap(a[i++], a[j--]);
	}
	if (i < r)
		qsort(i, r);
	if (l < j)
		qsort(l, j);
}

注意 \(5,7,11\) 小于 \(3\) 位,需要特判。

\(\mathrm{Code:}\)

#include <bits/stdc++.h>
using namespace std;
int l, r, sum, a[1000000];

int reverse(int n) {
	int a[10], i, sum = 0, t = n;
	for (i = 0; n > 0; i++, n /= 10) {
		a[i] = n % 10;
	}
	for (int j = 1; j < i; j++) {
		sum = sum * 10 + a[j];
	}
	return sum + t * pow(10, i - 1);
}

bool prime(int n) {
	if (n == 1) {
		return false;
	}
	if (n == 2) {
		return true;
	}
	if (n % 3 == 0) {
		return false;
	}
	for (int i = 7; i * i <= n; i++) {
		if (n % i == 0) {
			return false;
		}
	}
	return true;
}

void qsort(int l, int r) {
	int i = l, j = r, mid = a[(l + r) / 2];
	while (i <= j) {
		while (a[i] < mid)
			i++;
		while (a[j] > mid)
			j--;
		if (i <= j)
			swap(a[i++], a[j--]);
	}
	if (i < r)
		qsort(i, r);
	if (l < j)
		qsort(l, j);
}

void dfs(int i) {
	int x = reverse(i);
	if (x > r) {
		return;
	}
	if (prime(x) && x != 7 && x >= l) {
		a[sum++] = x;
	}
	for (int j = 0; j < 10; j++) {
		if (i * i < r) {
			dfs(i * 10 + j);
		} else {
			return;
		}
	}
}

int main() {
	cin >> l >> r;
	if (l == 5) {
		a[0] = 5;
		a[1] = 7;
		a[2] = 11;
		sum = 3;
	} else if (l <= 7) {
		a[0] = 7;
		a[1] = 11;
		sum = 2;
	} else if (l <= 11) {
		a[sum++] = 11;
	}
	dfs(1);
	dfs(3);
	dfs(7);
	dfs(9);
	qsort(0, sum - 1);
	for (int i = 0; i < sum; i++) {
		cout << a[i] << '\n';
	}
	return 0;
}

即可 \(\mathrm{AC}\)。

R0013. 「T3」街道赛跑 Solution

返回题目

题目分析:

核心思想:有向图 Dfs遍历。

首先我们要存图。虽然邻接表的确功能和优点很强大,但是这道题目50个点,100条边还是邻接矩阵好写多了。在练习邻接表的时候别忘记练习下邻接矩阵。

这道题目分两问,第一问其实很好做,怎么去搜索“不可避免的点”呢,只要把从这个点出发的所有边都标记为不通,然后再去看是不是所有点都被遍历了就可以了。

第二问的答案一定都包含在第一问的答案里面。所以我们可以直接搜索第一问的答案。从第一问的答案的那个点开始遍历,看那个点之前的点有没有被遍历到就可以了。

\(\mathrm{Code:}\)

#pragma(3,"Ofast")
#include <iostream>
using namespace std;
bool m[51][51], vis[51], vis2[51];
int a[51], a2[51], p1, p2, p3 = 0;
#define int register int

bool dfs1(int x) {
	if (vis[x]) {
		return false;
	}
	if (x == p3) {
		return true;
	}
	vis[x] = true;
	for (int i = 0; i <= p3; i++) {
		if (m[x][i] ) {
			if (dfs1(i)) {
				return true;
			}
		}
	}
	return false;
}

bool dfs2(int x) {
	if (vis[x]) {
		return true;
	}
	if (vis2[x]) {
		return false;
	}
	vis2[x] = true;
	for (int i = 0; i <= p3; i++) {
		if (m[x][i]) {
			if (dfs2(i)) {
				return true;
			}
		}
	}
	return false;
}
#undef int

int main() {
#define int register int
	ios::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL);
	while (true) {
		int t;
		cin >> t;
		if (t == -1) {
			break;
		}
		if (t == -2) {
			p3++;
		} else {
			m[p3][t] = true;
		}
	}
	p3--;
	for (int i = 1; i <= p3 - 1; i++) {
		for (int j = 0; j <= p3; j++) {
			vis[j] = false;
		}
		vis[i] = true;
		for (int j = 0; j <= p3; j++) {
			vis2[j] = false;
		}
		if (!dfs1(0)) {
			a[p1++] = i;
			vis[i] = false;
			if (!dfs2(i)) {
				a2[p2++] = i;
			}
		}
	}
	cout << p1;
	for (int i = 0; i <= p1 - 1; i++) {
		cout << " " << a[i];
	}
	cout << endl << p2;
	for (int i = 0; i <= p2 - 1; i++) {
		cout << " " << a2[i];
	}
	return 0;
}

我写题解的怎么可能给你 \(\mathrm{WA}\) 代码蛋子?这代码绝对保 \(\mathrm{AC}\)。

标签:10,return,OJ,Criss,int,题解,sum,++,mathrm
From: https://www.cnblogs.com/ymxx-home/p/R001Solution.html

相关文章

  • 洛谷 P3530 / bzoj2788【tarjan】【差分约束】
    判断是否有解可以使用差分约束。求解赛车手的成绩的取值可以使用Floyd。但是\(O(n^3)\)会TLE。可以先进行一次缩点。然后进行Floyd求出每一个连通块内的最长路径......
  • AtCoder Regular Contest 150 (ARC150) - A+B+C+D 题解
    A题意给定一个由0,1和?组成的长为\(n\)序列,其中?需要被替换为0或1,询问是否有且仅有一种?的替换方案使得序列中有\(k\)个1并且这\(k\)个1是连续的序......
  • TZOJ 7685: 最短路径 (dijstra/输出路径pre)
    描述  给定n个顶点的带权有向图,若从顶点x到顶点y之间存在一条路径,那么这条路径的长度定义为路径上各条边的权值之和。现在请你找出从顶点1到顶点n的一条最短路径。......
  • 你最喜欢用哪个emo表情?年度最常用 Emoji 有哪些?
    最常用的emoji表情是什么?你能猜到是哪个吗?在近日,非营利机构UnicodeConsortium统计了互联网最常用的emoji字符表情,每天都有数十亿个emoji被用于表达爱意、感谢、祝贺,......
  • [题解]守护者的挑战
    题目描述打开了黑魔法师Vani的大门,队员们在迷宫般的路上漫无目的地搜寻着关押applepi的监狱的所在地。突然,眼前一道亮光闪过。“我,Nizem,是黑魔法圣殿的守卫者。如果你能通......
  • Luogu P6880 [JOI 2020 Final] オリンピックバス 题解
    [P6880JOI2020Final]オリンピックバス-洛谷|计算机科学教育新生态(luogu.com.cn)两条前置知识:在图\(G\)上构造根为\(x\)的最短路树\(T\),我们删除任意一条......
  • ARC150 A+C题题解。
    如题,ARC150A题C题的解题报告。#A-Continuous1###题意:有1,0,?组成的一个序列(?可以为0/1),问恰好有且仅有k个i,且连续的情况有多少种。###分析:考虑O(n).常见为转......
  • P6772 [NOI2020] 美食家 题解
    一道不错的题目。一个朴素的dp就是\(f_{i,x}\)表示时间\(i\)时从1走到\(x\)的最大美味值,就有转移\(f_{i,v_j}=\max\{f_{i-w_j,u_j}+c_{v_j}+美食节贡献\}\),结......
  • 由 粗 到 精 学 习 LVI-SAM:imageProjection模块
    一、LVI-SAM的节点关系运行LVI-SAM,并打开rqt_graph,查看节点关系如图所示:激光雷达原始数据的topic为/points_raw,观察发现它仅被imageProjection节点订阅,因此我们分析这个节点......
  • 校内集训 小朋友的数字 题解
    校内集训小朋友的数字题解目录校内集训小朋友的数字题解题目分析思路代码题目不想调格式了,直接粘截图了……分析这道题就是简简单单的贪心,再加上个前缀和就行......