【补题笔记】杭州师范大学第四届程序设计新生赛

比赛链接

A - 解开束缚缠丝Ⅱ

(0:10, +)
题目链接

统计相同字符出现个数,如果个数是偶数,那么都可以对称地塞入回文串;如果是奇数,那么其最大偶数部分,也就是个数-1可以对称地塞入回文串。如果个数中有奇数,就可以将其中一个计数的单个字母塞到回文串的中间。

#include
using namespace std;
typedef long long LL;

int n;
int cnt[130];
int one = 0, ans = 0;

void main2() {
	cin >> n;
	for (int i = 'a'; i <= 'z'; ++i) {
		cnt[i] = 0;
	}
	for (int i = 'A'; i <= 'Z'; ++i) {
		cnt[i] = 0;
	}
	for (int i = 1; i <= n; ++i) {
		string x; cin >> x;
		cnt[x[0]]++;
	}
	one = ans = 0;
	for (int i = 'A'; i <= 'Z'; ++i) {
		if (cnt[i] % 2 != 0) {
			one = 1;
			ans += (cnt[i] - 1);
		}
		else ans += cnt[i];
	}
	for (int i = 'a'; i <= 'z'; ++i) {
		if (cnt[i] % 2 != 0) {
			one = 1;
			ans += (cnt[i] - 1);
		}
		else ans += cnt[i];
	}
	cout << ans + (one == 1) << '\n';
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	LL _;
	cin >> _;
//	_ = 1;
	while (_--) main2();
	return 0;
}

B - 7的意志

(0:35, +)
题目链接

先前缀和预处理,然后枚举每一个可能的区间和的左端点,寻找可行的右端点。一个左端点至多有一个可行的右端点匹配。

#include
using namespace std;
typedef long long LL;

int n, ans;
int a[100005], pre[100005];

void main2() {
	cin >> n; 
	pre[0] = ans = 0;
	for (int i = 1; i <= n; ++i) {
		cin >> a[i];
		pre[i] = pre[i - 1] + a[i];
	}
	for (int i = 1; i <= n; ++i) {
		LL tar = pre[i - 1] + 7777;
		LL x = lower_bound(pre + 1, pre + n + 1, tar) - pre;
		if (pre[x] == tar) ++ans;
	}
	cout << ans << '\n';
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	LL _;
	cin >> _;
//	_ = 1;
	while (_--) main2();
	return 0;
}

C - 迷宫的十字路口

(补)
题目链接

完完全全的没有思维的暴力。(比赛的时候想太多了)

流程中需要存储每一个时间点的所有信息。按照流程,更新每一个物品的坐标、自己的位置、自己拿到的物品数。因为物品数和操作数很小,所以纯暴力完全可以通过。只不过要注意,自己没动也可能会拿到物品,因为物品会自己跑过来。

#include
using namespace std;
typedef long long LL;

int n, q, px[2005], py[2005], ans[2005];
int x[2005][2005], y[2005][2005];
int a[2005], b[2005], op[2005], vis[2005][2005];

void main2() {
	cin >> n;
	for (int i = 1; i <= n; ++i) {
		cin >> x[0][i] >> y[0][i];
		vis[0][i] = 0;
	} 
	cin >> q;
	for (int i = 1; i <= q; ++i) {
		cin >> op[i];
		if (op[i] == 1) {
			string ss; cin >> ss;
			if (ss[0] == 'X') a[i] = 1;
			else a[i] = 2;
			cin >> b[i];
		}
		else if (op[i] == 2) {
			string ss; cin >> ss;
			if (ss[0] == 'X') a[i] = 1;
			else a[i] = 2;
		}
		else if (op[i] == 4) {
			cin >> a[i];
		}
	}
	px[0] = py[0] = ans[0] = 0;
	for (int i = 1; i <= q; ++i) {
		ans[i] = ans[i - 1]; 
		px[i] = px[i - 1]; 
		py[i] = py[i - 1];
		if (op[i] == 4) {
			memcpy(x[i], x[a[i] - 1], sizeof(x[i]));
			memcpy(y[i], y[a[i] - 1], sizeof(y[i]));
			memcpy(vis[i], vis[a[i] - 1], sizeof(vis[i]));
			ans[i] = ans[a[i] - 1];
			px[i] = px[a[i] - 1];
			py[i] = py[a[i] - 1];
			continue;
		}
		memcpy(x[i], x[i - 1], sizeof(x[i]));
		memcpy(y[i], y[i - 1], sizeof(y[i]));
		memcpy(vis[i], vis[i - 1], sizeof(vis[i]));
		if (op[i] == 1) {
			if (a[i] == 1) {
				int l = min(px[i], px[i] + b[i]);
				int r = max(px[i], px[i] + b[i]);
				px[i] += b[i];
				if (px[i] != 0 and py[i] != 0) {
					px[i] = py[i] = 0; continue;
				}
				for (int j = 1; j <= n; ++j) {
					if (!vis[i][j] and y[i][j] == 0 and l <= x[i][j] and x[i][j] <= r) {
						vis[i][j] = 1; ++ans[i];
					}
				}
			}
			else {
				int l = min(py[i], py[i] + b[i]);
				int r = max(py[i], py[i] + b[i]);
				py[i] += b[i];
				if (px[i] != 0 and py[i] != 0) {
					px[i] = py[i] = 0; continue;
				}
				for (int j = 1; j <= n; ++j) {
					if (!vis[i][j] and x[i][j] == 0 and l <= y[i][j] and y[i][j] <= r) {
						vis[i][j] = 1; ++ans[i];
					}
				}
			}
		}
		else if (op[i] == 2) {
			if (a[i] == 1) {
				for (int j = 1; j <= n; ++j) {
					x[i][j] = -x[i][j];
				}
			}
			else {
				for (int j = 1; j <= n; ++j) {
					y[i][j] = -y[i][j];
				}
			}
		}
		else if (op[i] == 3) {
			for (int j = 1; j <= n; ++j) {
				swap(x[i][j], y[i][j]);
			}
		}
		for (int j = 1; j <= n; ++j) {
			if (!vis[i][j] and px[i] == x[i][j] and py[i] == y[i][j]) {
				++ans[i]; vis[i][j] = 1;
				break;
			}
		}
	}
	cout << ans[q];
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	LL _;
//	cin >> _;
	_ = 1;
	while (_--) main2();
	return 0;
}

D - 转动命运之轮

(2:58, +1)
题目链接

打表找规律题。根据排列的性质,如果是统计所有排列的情况,那么所有排列进行完后,每一个人传递玩具的总次数(对于所有排列的情况的总次数)一定是相同的,感性理解是非常容易的。也就是说,如果题目中给出的快乐值之和我们设为 x x x,那么答案一定是一个系数 p p p x x x的乘积。

然后模拟 n = 1 , 2 , ⋯   , 5 n=1,2,\cdots,5 n=1,2,,5,发现系数 p p p的值分别等于 1 , 3 , 12 , 60 , 360 1,3,12,60,360 1,3,12,60,360。也就是说,如果 p p p是一个序列,则满足 p 1 = 1 , p i + 1 = p i × 3 ( i > 0 ) p_1=1,p_{i+1}=p_i\times 3(i > 0) p1=1,pi+1=pi×3(i>0)

(因为求和的 x x x没取模wa了一发)

#include
using namespace std;
typedef long long LL;
const LL mod = 998244353;

LL n, sum = 0, tmp = 1;
LL a[2005];

void main2() {
	cin >> n;
	for (int i = 1; i <= n; ++i) {
		cin >> a[i];
		sum = (sum + a[i]) % mod;
	}
	for (int i = 2; i <= n; ++i) {
		tmp = (tmp * (i + 1)) % mod;
	}
	cout << (sum * tmp) % mod;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	LL _;
//	cin >> _;
	_ = 1;
	while (_--) main2();
	return 0;
}

E - 计算最小值

(1:36, +1)
题目链接

对每一行的数据进行排序,将所有的数放到一个数组 b b b中,对整个数组再进行一次排序。

根据题目的操作,我们发现所选取的数中所求最小值,其实就是所选取的最大值与最小值的差。也就是说,我们要在每一行选取一个数,要让这些数的极差最小。

我们在排好序的数组 b b b中枚举起点,也就是选取的数的最小点。然后从小到大看每一行的数据中最小一个大于等于起点的数,记录这些数的答案。由于每一行的数据指针过程是单向的,所以可以记录指针上一次所在的位置,下一次要更新的时候直接从那个位置向右移。

最终取所有可行极差的最小值。

#include
using namespace std;
typedef long long LL;

int n, m;
int a[12][1000005];
int b[1000005], c[12];
int bi = 0, res = 1e9;

void main2() {
	cin >> n >> m;
	for (int i = 1; i <= n; ++i) {
		c[i] = 1;
	}
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= m; ++j) {
			cin >> a[i][j];
			b[++bi] = a[i][j];
		}
	}
	for (int i = 1; i <= n; ++i) {
		sort(a[i] + 1, a[i] + m + 1);
	}
	sort(b + 1, b + n * m + 1);
	for (int i = 1; i <= n * m; ++i) {
		int mx = 0, ok = 1;
		for (int j = 1; j <= n; ++j) {
			while (c[j] <= m and a[j][c[j]] < b[i]) {
				++c[j];
			}
			if (c[j] > m) {
				ok = 0; break;
			}
			mx = max(mx, a[j][c[j]] - b[i]);
		}
		if (!ok) break;
		res = min(res, mx);
	}
	cout << res << '\n';
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	LL _;
//	cin >> _;
	_ = 1;
	while (_--) main2();
	return 0;
}

F - 月光奏鸣曲

(0:48, +2)
题目链接

忘记答案可以是 0 0 0了,连跪两发,蚌。

直接求出旋转 1 1 1次的两种方阵和 2 2 2次的一种方阵,直接逐位比较即可。

#include
using namespace std;
typedef long long LL;

int n;
int a[25][25], b[25][25];

bool check0() {
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= n; ++j) {
			if (b[i][j] != a[i][j]) return false;
		}
	}
	return true;
}

bool check1() {
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= n; ++j) {
			if (b[i][j] != a[n - j + 1][i]) return false;
		}
	}
	return true;
}

bool check2() {
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= n; ++j) {
			if (b[i][j] != a[j][n - i + 1]) return false;
		}
	}
	return true;
}

bool check3() {
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= n; ++j) {
			if (b[i][j] != a[n - i + 1][n - j + 1]) return false;
		}
	}
	return true;
}

void main2() {
	cin >> n;
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= n; ++j) {
			cin >> a[i][j];
		}
	}
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= n; ++j) {
			cin >> b[i][j];
		}
	}
	if (check0()) cout << 0 << '\n';
	else if (check1()) cout << 1 << '\n';
	else if (check2()) cout << 1 << '\n';
	else if (check3()) cout << 2 << '\n';
	else cout << -1 << '\n';
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	LL _;
	cin >> _;
//	_ = 1;
	while (_--) main2();
	return 0;
}

G - 电子表校对

(2:18, +)
题目链接

算个时差,只是输入输出麻烦一点。我这里是直接拆成三段字符串,用map来映射。

#include
using namespace std;
typedef long long LL;

map<string, int> mp;
map<int, string> pm;

void get_mp() {
	mp[" _ | ||_|"] = 0; pm[0] = " _ | ||_|";
	mp["     |  |"] = 1; pm[1] = "     |  |";
	mp[" _  _||_ "] = 2; pm[2] = " _  _||_ ";
	mp[" _  _| _|"] = 3; pm[3] = " _  _| _|";
	mp["   |_|  |"] = 4; pm[4] = "   |_|  |";
	mp[" _ |_  _|"] = 5; pm[5] = " _ |_  _|";
	mp[" _ |_ |_|"] = 6; pm[6] = " _ |_ |_|";
	mp[" _   |  |"] = 7; pm[7] = " _   |  |";
	mp[" _ |_||_|"] = 8; pm[8] = " _ |_||_|";
	mp[" _ |_| _|"] = 9; pm[9] = " _ |_| _|";
}

string r1, r2, r3;
int a[8], b[8], c[8];
int h1, m1, s1, t1, h2, m2, s2, t2, d, hd, md, sd;

void main2() {
	getline(cin, r1);
	getline(cin, r2);
	getline(cin, r3);
	for (int i = 0; i < 6; ++i) {
		string x = r1.substr(i * 3, 3) + r2.substr(i * 3, 3) + r3.substr(i * 3, 3);
		a[i] = mp[x];
	}
	getline(cin, r1);
	getline(cin, r2);
	getline(cin, r3);
	for (int i = 0; i < 6; ++i) {
		string x = r1.substr(i * 3, 3) + r2.substr(i * 3, 3) + r3.substr(i * 3, 3);
		b[i] = mp[x];
	}
	s1 = a[4] * 10 + a[5]; s2 = b[4] * 10 + b[5];
	m1 = a[2] * 10 + a[3]; m2 = b[2] * 10 + b[3];
	h1 = a[0] * 10 + a[1]; h2 = b[0] * 10 + b[1];
	t1 = s1 + m1 * 60 + h1 * 3600;
	t2 = s2 + m2 * 60 + h2 * 3600;
	if (t1 == t2) {
		cout << "gang gang hao\n";
		hd = md = sd = 0;
	}
	else if (t1 < t2) {
		cout << "late\n";
		d = t2 - t1;
		hd = d / 3600; d -= hd * 3600;
		md = d / 60; d -= md * 60;
		sd = d;
	}
	else {
		cout << "early\n";
		d = t1 - t2;
		hd = d / 3600; d -= hd * 3600;
		md = d / 60; d -= md * 60;
		sd = d;
	}
	c[0] = hd / 10; c[1] = hd % 10;
	c[2] = md / 10; c[3] = md % 10;
	c[4] = sd / 10; c[5] = sd % 10;
	string x;
	for (int i = 0; i < 3; ++i) {
		x = "";
		for (int j = 0; j <= 5; ++j) {
			x += pm[c[j]].substr(i * 3, 3);
		}
		cout << x << '\n';
	}
}

int main() {
//	ios::sync_with_stdio(false);
//	cin.tie(0); cout.tie(0);
	LL _;
	get_mp();
//	cin >> _;
	_ = 1;
	while (_--) main2();
	return 0;
}

H - 简单的 LRU 问题

(3:33, +1)
题目链接

按照流程模拟一下就好了,输出的表格比较繁琐,但也比较好做。

#include
using namespace std;
typedef long long LL;

int n, m, mx;
int a[105][10];
string hx = "0123456789abcdef";

void main2() {
	cin >> n >> m;
	mx = 0;
	cout << "+------+";
	for (int i = 0; i < n; ++i) {
		cout << "--------+";
	}
	cout << '\n';
	cout << "|      |";
	for (int i = 0; i < n; ++i) {
		cout << "  0x";
		int a = i / 16, b = i % 16;
		cout << hx.substr(a, 1) << hx.substr(b, 1) << "  |";
	}
	cout << '\n';
	cout << "+------+";
	for (int i = 0; i < n; ++i) {
		cout << "--------+";
	}
	cout << '\n';
	for (int i = 0; i < m; ++i) {
		int x; cin >> x;
		if (i == 0) a[0][0] = x;
		else {
			int have = 0;
			for (int j = 0; j <= mx; ++j) {
				if (a[i - 1][j] == x) {
					have = 1; break;
				}
			}
			if (have) {
				int k = 0;
				for (int j = 0; j <= mx; ++j) {
					if (a[i - 1][j] == x) continue;
					a[i][k++] = a[i - 1][j];
				}
				a[i][mx] = x;
			}
			else {
				if (mx < n - 1) {
					for (int j = 0; j <= mx; ++j) {
						a[i][j] = a[i - 1][j];
					}
					a[i][++mx] = x;
				}
				else {
					int k = 0;
					for (int j = 1; j <= mx; ++j) {
						a[i][k++] = a[i - 1][j];
					}
					a[i][mx] = x;
				}
			}
		}
		cout << "| 0x";
		int A, B, C, D; A = i / 16; B = i % 16;
		cout << hx.substr(A, 1) << hx.substr(B, 1) << " |";
		for (int j = 0; j <= mx; ++j) {
			cout << " 0x";
			int tmp = a[i][j];
			A = tmp / 4096; tmp -= A * 4096;
			B = tmp / 256; tmp -= B * 256;
			C = tmp / 16; tmp -= C * 16;
			D = tmp;
			cout << hx.substr(A, 1) << hx.substr(B, 1);
			cout << hx.substr(C, 1) << hx.substr(D, 1) << " |";
		}
		for (int j = mx + 1; j < n; ++j) {
			cout << "        |";
		}
		cout << '\n';
		cout << "+------+";
		for (int i = 0; i < n; ++i) {
			cout << "--------+";
		}
		cout << '\n';
	}
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	LL _;
//	cin >> _;
	_ = 1;
	while (_--) main2();
	return 0;
}

I - 好想听肆宝唱歌啊

(0:05, +)
题目链接

结构体排序。

#include
using namespace std;
typedef long long LL;

int n;

struct SONG {
	int w;
	string x;
}s[100005];

void main2() {
	cin >> n;
	for (int i = 1; i <= n; ++i) {
		cin >> s[i].w >> s[i].x;
	}
	sort(s + 1, s + n + 1, [](const SONG &A, const SONG &B) {
		return A.w > B.w;
	});
	int y; cin >> y;
	cout << s[y + 1].x;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	LL _;
//	cin >> _;
	_ = 1;
	while (_--) main2();
	return 0;
}

J - 毁灭凤凰人

(0:20, +1)
题目链接

竟然能在算法竞赛中看到游戏王,太过激动而把题读错,成功wa了一发

#include
using namespace std;
typedef long long LL; 

int n, m;
int mxa = 0, a = 0, b = 0;

void main2() {
	cin >> n >> m;
	for (int i = 1; i <= n; ++i) {
		int o, x; cin >> o;
		if (o == 0) {
			cin >> x;
			mxa = max(mxa, x);
		}
		else if (o == 1) a = 1;
		else b = 1;
	}
	if (m == 0 and mxa >= 2500 and a) {
		cout << "haoye\n";
		return;
	}
	else if (m == 1 and mxa > 2100 and a) {
		cout << "haoye\n";
		return;
	}
	else if (b and n > 1) {
		cout << "haoye\n";
		return;
	}
	else cout << "QAQ\n";
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	LL _;
//	cin >> _;
	_ = 1;
	while (_--) main2();
	return 0;
}

K - 欢迎来到杭师大

(0:02, +)
题目链接

#include
using namespace std;
typedef long long LL;

int n;

void main2() {
	cin >> n;
	for (int i = 1; i <= n; ++i) {
		cout << "Welcome to HZNU\n";
	}
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	LL _;
//	cin >> _;
	_ = 1;
	while (_--) main2();
	return 0;
}

L - Ayanoto 变形记

(0:01, +)
题目链接

只有 x = 0 x=0 x=0时输出no。

#include
using namespace std;
typedef long long LL;

int n, x;

void main2() {
	cin >> n >> x;
	if (x == 0) cout << "no\n";
	else cout << "yes\n";
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	LL _;
	cin >> _;
//	_ = 1;
	while (_--) main2();
	return 0;
}

M - P龙学长的教诲

(0:28, +)
题目链接

记录结尾标点,然后按照特定顺序把单词输出出来就行了。

#include
using namespace std;
typedef long long LL;

int n;
string x[1005];
char note;

void print(int id) {
	if (id != n) cout << x[id];
	else {
		int len = x[id].length();
		for (int i = 0; i < len - 1; ++i) {
			cout << x[id][i];
		}
	}
}

void main2() {
	n = 0;
	while (1) {
		cin >> x[++n];
		int len = x[n].length();
		if (x[n][len - 1] == '.' or x[n][len - 1] == '!' or x[n][len - 1] == '?') {
			note = x[n][len - 1];
			break;
		}
	}
	for (int i = 1; i <= n / 2; ++i) {
		print(i); 
		cout << ' ';
		print(n - i + 1);
		if (i < n / 2 or n % 2 == 1)cout << ' ';
	}
	if (n % 2 == 1) {
		print(n / 2 + 1);
	}
	cout << note << '\n';
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	LL _;
	cin >> _;
//	_ = 1;
	while (_--) main2();
	return 0;
}

你可能感兴趣的:(算法学习,做题笔记,算法,c++)