首页 > 编程语言 >2023年中国高校计算机大赛-团队程序设计天梯赛(GPLT)上海理工大学校内选拔赛

2023年中国高校计算机大赛-团队程序设计天梯赛(GPLT)上海理工大学校内选拔赛

时间:2023-03-11 21:12:06浏览次数:57  
标签:ch int res while 上海理工大学 2023 GPLT include getchar

https://ac.nowcoder.com/acm/contest/52244

A - A Xor B Problem

给定序列 \(a_i\),求有多少数对 \((i, j)\) 满足 \(a_i\oplus a_j = 0\),其中 \(\oplus\) 表示按位异或

\(a_i\oplus a_j = 0\) 等价于 \(a_i = a_j\),对 \(a_i\) 排序,直接计算即可

点击查看代码
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
#include <cstring>
#include <functional>

#define i64 long long

inline int read() {
	bool sym = 0; int res = 0; char ch = getchar();
	while (!isdigit(ch)) sym |= (ch == '-'), ch = getchar();
	while (isdigit(ch)) res = (res << 3) + (res << 1) + (ch ^ 48), ch = getchar();
	return sym ? -res : res;
}

int main() {
	int n = read(), a[n + 1];
	for (int i = 1; i <= n; i++) a[i] = read();
	std::sort(a + 1, a + n + 1);
	i64 res = 0, ans = 0;
	for (int i = 1; i <= n; i++) {
		res = 1;
		while (a[i] == a[i + 1] && i <= n) i++, res++;
		ans += res * (res - 1);
	}
	printf("%lld", ans + n);
	return 0;
}

B - 吃苹果

给定 \(a_i, b_i\) 两个序列,对于每个 \(i\),只能选择 \(a_i, b_i\) 中的一个数提供贡献,求刚好选择 \(k\) 个 \(b_i\) 中的数最大的贡献

如果全选 \(a_i\),每把一个 \(a_i\) 换成 \(b_i\) 的贡献为 \(b_i - a_i\),以 \(b_i - a_i\) 为关键字排序,取前 \(k\) 个转化即可

点击查看代码
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
#include <cstring>
#include <functional>

#define i64 long long

inline int read() {
	bool sym = 0; int res = 0; char ch = getchar();
	while (!isdigit(ch)) sym |= (ch == '-'), ch = getchar();
	while (isdigit(ch)) res = (res << 3) + (res << 1) + (ch ^ 48), ch = getchar();
	return sym ? -res : res;
}

class DAT {
public:
	int a, b;
};

int main() {
	int n = read(), k = read(); DAT dat[n + 1];
	for (int i = 1; i <= n; i++) dat[i] = (DAT){read(), read()};
	auto cmp = [](DAT A, DAT B) -> bool {
		return A.a - A.b < B.a - B.b;
	};
	std::sort(dat + 1, dat + n + 1, cmp);
	int ans = 0;
	for (int i = 1; i <= k; i++) ans += dat[i].b;
	for (int i = k + 1; i <= n; i++) ans += dat[i].a;
	printf("%d", ans);
	return 0;
}

C - n皇后问题

\(n\) 次询问 \((x, y)\) 位置放置一个皇后是否会被其它皇后攻击,并放置此皇后

两条斜线即一次函数 \(x + y = A\) 和 \(x - y = B\),维护每个函数是否已经被占领即可

点击查看代码
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
#include <cstring>
#include <functional>

#define i64 long long

inline int read() {
	bool sym = 0; int res = 0; char ch = getchar();
	while (!isdigit(ch)) sym |= (ch == '-'), ch = getchar();
	while (isdigit(ch)) res = (res << 3) + (res << 1) + (ch ^ 48), ch = getchar();
	return sym ? -res : res;
}

const int N = 1e6;

bool vis_1[N + 1], vis_2[N + 1], vis_3[2 * N + 1], vis_4[2 * N + 1];

int main() {
	int n = read(), m = read();
	for (int i = 1; i <= m; i++) {
		int x = read(), y = read();
		if (vis_1[x]) {printf("No\n"); continue;}
		if (vis_2[y]) {printf("No\n"); continue;}
		if (vis_3[x + y]) {printf("No\n"); continue;}
		if (vis_4[x - y + n]) {printf("No\n"); continue;}
		vis_1[x] = vis_2[y] = vis_3[x + y] = vis_4[x - y + n] = 1;
		printf("Yes\n");
	}
	return 0;
}

D - 分苹果

给定两条直线,求将 \(n\) 个苹果分成的四个区域各有多少苹果

判断每个点在每条线的下面还是上面即可

点击查看代码
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
#include <cstring>
#include <functional>

#define i64 long long

inline i64 read() {
	bool sym = 0; i64 res = 0; char ch = getchar();
	while (!isdigit(ch)) sym |= (ch == '-'), ch = getchar();
	while (isdigit(ch)) res = (res << 3) + (res << 1) + (ch ^ 48), ch = getchar();
	return sym ? -res : res;
}

int main() {
	i64 n = read(), a1, a2, b1, b2, c1, c2, a[4];
	memset(a, 0, sizeof(a));
	a1 = read(); b1 = read(); c1 = read();
	a2 = read(); b2 = read(); c2 = read();
	for (i64 i = 1; i <= n; i++) {
		i64 x = read(), y = read();
		if (a1 * x + b1 * y + c1 < 0) {
			if (a2 * x + b2 * y + c2 < 0) a[0]++;
			if (a2 * x + b2 * y + c2 > 0) a[1]++;
		}
		if (a1 * x + b1 * y + c1 > 0) {
			if (a2 * x + b2 * y + c2 < 0) a[2]++;
			if (a2 * x + b2 * y + c2 > 0) a[3]++;
		}
	}
	std::sort(a, a + 4);
	for (int i = 0; i < 4; i++) printf("%lld ", a[i]);
	return 0;
}

E - 完形填空

每个题有四个选项,一共 \(4n\) 个题,给定每个题每个选项正确的概率,求当每个选项正好选择 \(n\) 次期望正确的题目个数

因为每个题的收益都是 \(1\),则期望即概率

dp[i][A][B][C][D] 表示前 \(i\) 个题四个选项选择了一定次数的最高期望,转移枚举一下选择哪个选项即可

点击查看代码
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
#include <cstring>
#include <functional>

#define i64 long long

inline int read() {
	bool sym = 0; int res = 0; char ch = getchar();
	while (!isdigit(ch)) sym |= (ch == '-'), ch = getchar();
	while (isdigit(ch)) res = (res << 3) + (res << 1) + (ch ^ 48), ch = getchar();
	return sym ? -res : res;
}

int main() {
	int n = read(), a[n + 1][4];
	for (int i = 1; i <= n; i++) {
		for (int j = 0; j < 4; j++) a[i][j] = read();
	}
	int f[2][26][26][26][26];
	int m = n / 4;
	memset(f, 0, sizeof(f));
	for (int i = 1; i <= n; i++) {
		for (int A = 0; A <= m; A++) {
			for (int B = 0; B <= m; B++) {
				for (int C = 0; C <= m; C++) {
					for (int D = 0; D <= m; D++) {
						if (A + B + C + D == i) {
							if (A) f[i & 1][A][B][C][D] = std::max(f[i & 1][A][B][C][D], f[(i & 1) ^ 1][A - 1][B][C][D] + a[i][0]);
							if (B) f[i & 1][A][B][C][D] = std::max(f[i & 1][A][B][C][D], f[(i & 1) ^ 1][A][B - 1][C][D] + a[i][1]);
							if (C) f[i & 1][A][B][C][D] = std::max(f[i & 1][A][B][C][D], f[(i & 1) ^ 1][A][B][C - 1][D] + a[i][2]);
							if (D) f[i & 1][A][B][C][D] = std::max(f[i & 1][A][B][C][D], f[(i & 1) ^ 1][A][B][C][D - 1] + a[i][3]);
						}
					}
				}
			}
		}
	}
	printf("%d", f[0][m][m][m][m]);
	return 0;
}

F - 坐火车

求经历点数量最小的情况下 \(1\) 到 \(n\) 的最短路

由于边权大于 \(1\),所以直接跑最短路,第一关键字为边数,第二关键字为边权即可

也可以边权全设为 \(1\) 找出所有在 \(1\) 到 \(n\) 最短路上的边再次跑最短路

点击查看代码
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
#include <cstring>
#include <queue>
#include <functional>

#define i64 long long

inline int read() {
	bool sym = 0; int res = 0; char ch = getchar();
	while (!isdigit(ch)) sym |= (ch == '-'), ch = getchar();
	while (isdigit(ch)) res = (res << 3) + (res << 1) + (ch ^ 48), ch = getchar();
	return sym ? -res : res;
}

const int inf = 2e9 + 7;

class EDGE {
public:
	int u, v, nxt, dis; bool vis;
};

class NODE {
public:
    int id, dis;
    NODE(int a, int b) {id = a; dis = b;}
    bool operator < (const NODE& a) const {return dis > a.dis;}
};

int main() {
	int n = read(), m = read();
	int head[n + 1], w[m + 1], cnt = 0; EDGE edge[m * 2 + 1];
	memset(head, 0, sizeof(head));
	for (int i = 1; i <= m; i++) {
		int u = read(), v = read(); w[i] = read();
		edge[++cnt] = (EDGE){u, v, head[u], 1, 1}; head[u] = cnt;
		edge[++cnt] = (EDGE){v, u, head[v], 1, 1}; head[v] = cnt;
	}
	std::vector<int> dis1, disn, dis2;
	auto dijkstra = [&](int s) -> std::vector<int> {
		std::vector<int> dis(n + 1, inf);
		bool done[n + 1]; memset(done, 0, sizeof(done));
		std::priority_queue<NODE> q;
		q.push(NODE(s, 0)); dis[s] = 0;
		while (!q.empty()) {
			int u = q.top().id; q.pop();
			if (done[u]) continue; done[u] = 1;
			for (int e = head[u]; e; e = edge[e].nxt) {
				if (!edge[e].vis) continue;
				int v = edge[e].v, t = edge[e].dis;
				if (done[v]) continue;
				if (dis[u] + t < dis[v]) {
					dis[v] = dis[u] + t;
					q.push(NODE(v, dis[v]));
				}
			}
		}
		return dis;
	};
	dis1 = dijkstra(1);
	disn = dijkstra(n);
	int D = dis1[n]; printf("%d ", D + 1);
	// for (int i = 1; i <= n; i++) printf("%d ", dis1[i]); puts("");
	// for (int i = 1; i <= n; i++) printf("%d ", disn[i]); puts("");
	for (int u = 1; u <= n; u++) {
		for (int e = head[u]; e; e = edge[e].nxt) {
			int v = edge[e].v, t = edge[e].dis;
			if (dis1[u] + t + disn[v] != D && disn[u] + t + dis1[v] != D) {
				// printf("%d %d\n", u, v);
				edge[e].vis = 0;
			}
		}
	}
	for (int i = 1; i <= m; i++) {
		edge[i * 2].dis = w[i];
		edge[i * 2 - 1].dis = w[i];
	}
	dis2 = dijkstra(1); printf("%d", dis2[n]);
	return 0;
}

G - A Xor B Problem again

给定序列 \(a_i\),求有多少数对 \((i, j)\) 满足 \(a_i\oplus a_j = a_i + b_j\),其中 \(\oplus\) 表示按位异或

对于每个 \(a_i\),存在贡献的数即为自己补集的子集,于是使用高维前缀和计算出来每个集合的贡献,直接计算即可

点击查看代码
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
#include <cstring>
#include <functional>

#define i64 long long

inline int read() {
	bool sym = 0; int res = 0; char ch = getchar();
	while (!isdigit(ch)) sym |= (ch == '-'), ch = getchar();
	while (isdigit(ch)) res = (res << 3) + (res << 1) + (ch ^ 48), ch = getchar();
	return sym ? -res : res;
}

int main() {
	int n = read(), m = 0, a[n + 1];
	for (int i = 1; i <= n; i++) {
		a[i] = read(); m = std::max(m, a[i]);
	}
	int vis[1 << 18];
	memset(vis, 0, sizeof(vis));
	for (int i = 1; i <= n; i++) vis[a[i]]++;
	for (int j = 0; j < 17; j++) {
		for (int i = 0; i < 1 << 17; i++) {
			if (i >> j & 1) vis[i] += vis[i ^ 1 << j];
		}
	}
	i64 ans = 0;
	for (int i = 1; i <= n; i++) {
		ans += vis[(1 << 17) - 1 ^ a[i]];
	}
	printf("%lld", ans);
	return 0;
}

H - 摘苹果

对序列支持 \(3\) 种操作,区间对所有大于等于 \(10\) 的数乘 \(2/3\),查询区间小于 \(100\) 的数的个数,查询区间和

经典线段树,维护一个区间最大值,一个区间和,区间小于 \(100\) 的数的个数,修改时查询当前区间最大值若小于 \(10\) 直接返回,这样每个位置只会被修改 \(log\) 次,总体复杂度 \(O(m\log n)\)

点击查看代码
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
#include <cstring>
#include <functional>

#define i64 long long

inline int read() {
	bool sym = 0; int res = 0; char ch = getchar();
	while (!isdigit(ch)) sym |= (ch == '-'), ch = getchar();
	while (isdigit(ch)) res = (res << 3) + (res << 1) + (ch ^ 48), ch = getchar();
	return sym ? -res : res;
}

class SEG_TREE {
	#define ls x << 1
	#define rs x << 1 | 1
public:
	std::vector<int> cnt, max, a;
	std::vector<i64> sum;
	void init(int n) {
		a.resize(n + 1);
		max.resize(n * 4 + 1);
		cnt.resize(n * 4 + 1);
		sum.resize(n * 4 + 1);
	}
	void pushup(int x) {
		max[x] = std::max(max[ls], max[rs]);
		sum[x] = sum[ls] + sum[rs];
		cnt[x] = cnt[ls] + cnt[rs];
	}
	void build(int x, int l, int r) {
		if (l == r) {
			max[x] = a[l];
			sum[x] = a[l];
			cnt[x] = a[l] < 100;
			return;
		}
		int mid = l + r >> 1;
		build(ls, l, mid);
		build(rs, mid + 1, r);
		pushup(x);
	}
	void modify(int x, int l, int r, int L, int R) {
		if (max[x] < 10) return;
		if (l == r) {
			max[x] -= (max[x] + 2) / 3;
			sum[x] -= (sum[x] + 2) / 3;
			cnt[x] = max[x] < 100;
			return;
		}
		int mid = l + r >> 1;
		if (mid >= L) modify(ls, l, mid, L, R);
		if (mid + 1 <= R) modify(rs, mid + 1, r, L, R);
		pushup(x);
	}
	int query2(int x, int l, int r, int L, int R) {
		if (L <= l && r <= R) return cnt[x];
		int mid = l + r >> 1, res = 0;
		if (mid >= L) res += query2(ls, l, mid, L, R);
		if (mid + 1 <= R) res += query2(rs, mid + 1, r, L, R);
		return res;
	}
	i64 query3(int x, int l, int r, int L, int R) {
		if (L <= l && r <= R) return sum[x];
		int mid = l + r >> 1; i64 res = 0;
		if (mid >= L) res += query3(ls, l, mid, L, R);
		if (mid + 1 <= R) res += query3(rs, mid + 1, r, L, R);
		return res;
	}
};

int main() {
	int n = read(), m = read();
	SEG_TREE seg; seg.init(n);
	for (int i = 1; i <= n; i++) seg.a[i] = read();
	seg.build(1, 1, n);
	for (int i = 1; i <= m; i++) {
		int opt = read(), l = read(), r = read();
		if (opt == 1) seg.modify(1, 1, n, l, r);
		if (opt == 2) printf("%d\n", seg.query2(1, 1, n, l, r));
		if (opt == 3) printf("%lld\n", seg.query3(1, 1, n, l, r));
	}
	return 0;
}

标签:ch,int,res,while,上海理工大学,2023,GPLT,include,getchar
From: https://www.cnblogs.com/zrzring/p/GPLT2023.html

相关文章

  • 2023/3/8 && 2023/3/11 模拟总结
    开摆,嘿嘿,开摆!2023/3/8IOI赛制/6道题/部分文件io集训期间的第一次模拟,看到是IOI赛制感觉好拿分,于是就挺放松的。开考之后看到T1,胡了一个二维前缀和暴力做法,爽拿3......
  • 2023年3月11日软工日报
    今天早上一直休息,下午写了个四级阅读,太菜,没法过,随缘吧,晚上我把那个app打卡不能重复打卡功能写了下。展示下,但是对我是知道的,我只是展示我填的语句switch(view.get......
  • 2023-03-11 Java中的动态数组
    类似C++中的vector,动态数组需要满足以下功能增(insert)删(remove)改(set)查(get和contain)支持泛型自动扩容和缩容上面的实现实际相当于JDK标准库中的java.util......
  • Keil MDK6要来了,将嵌入式软件开发水平带到新高度,支持跨平台(2023-03-11)
    注:这个是MDK6,不是MDK5AC6,属于下一代MDK视频版:https://www.bilibili.com/video/BV16s4y157WF一年一度的全球顶级嵌入式会展EmbeddedWorld2023上,MDK6将展示预览版效......
  • 《渗透测试》HTTP数据包&Postman构造&请求方法&请求头修改&状态码判断 2023 Day10
    1    2请求头各参数及解释  3响应头参数及解释  4get请求  4post请求   -方法1、常规请求-Get2、用户登录-Post•get:向特定资......
  • GDKOI 2023 划水记
    在zsjz集训,正好能来划个水。赛前三场联考没过题,唯一写出来的一个还多测没清挂没了。赛前一天看了几个板子,发现自己好几个都不太会写,原因大概是因为我模拟赛全部只会裸......
  • 2023/3/10每日总结
    登录界面xml<?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent......
  • test20230304考试总结(2023春 · 字符串)
    前言赛时得分明细:ABCDTotalRank1001000702702C题如此说道:字符串没有学好的报应!!A.P4391[BOI2009]RadioTransmission无线传输题面给定一个字......
  • 2023-3-10
    2023-3-101对下列各题中指定的集合\(A\),求出\(A^{\circ}\),\(\overline{A}\),\(\partialA\):​ (1)在\(\R\)中,\(A=\{1,\frac{1}{2},\frac{1}{3},\cdots......
  • 连网技术与网络管理 2023-03-11
    交换机DHCP防护,防止一个局域网里面,有2个DHCP误接入第二个路由器,就会导致多个DHCP.DHCP是应用层的协议  Wireshark分析DHCP_琳小白的博客-CSDN博客 IP地址,网络地......