首页 > 编程语言 >2024年“华为杯”天津大学程序设计竞赛(新生赛)个人题解

2024年“华为杯”天津大学程序设计竞赛(新生赛)个人题解

时间:2024-12-23 12:09:49浏览次数:5  
标签:arr return int 题解 long 2024 maxn 天津大学 define

A.谁来自智算学部

模拟

#include<bits/stdc++.h>
#define int long long
#define pii piar<int, int>
#define db double 
using namespace std;
int ans[5];
void solve() {
	int n; cin >> n;
	while (n--) {
		string str; cin >> str;
		if (str.substr(4, 3) == "244") {
			ans[1]++;
			if (str[0] == '3') ans[2]++;
			else if (str[0] == '2') ans[3]++;
			else ans[4]++;
		}
	}
	for (int i = 1; i <= 4; i++)
		cout << ans[i] << " ";
}
signed main() {
	ios::sync_with_stdio(0),cin.tie(0), cout.tie(0);
	int t = 1;
	// cin >> t;
	while (t--) solve();
	return 0; 
}

B.加密呼叫

模拟矩阵乘法

#include<bits/stdc++.h>
#define int long long
#define pii piar<int, int>
#define db double 
using namespace std;
const int maxn = 1e3 + 10;
int a[maxn][maxn], b[maxn][maxn], c[maxn][maxn];
void solve() {
	int n, m; cin >> n >> m;
	for (int i = 1; i <= n; i++) cin >> a[1][i];
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++)
		 	cin >> b[i][j];
	for (int i = 1; i <= m; i++) {
		int ans = 0;
		for (int j = 1; j <= n; j++)
			ans += a[1][j] * b[j][i];
		cout << ans << "\n";
	}
}
signed main() {
	ios::sync_with_stdio(0),cin.tie(0), cout.tie(0);
	int t = 1;
	// cin >> t;
	while (t--) solve();
	return 0; 
}

C.小J打大金

每遇到9看最近一局是否1-8都有出现

#include<bits/stdc++.h>
#define int long long
#define pii piar<int, int>
#define db double 
using namespace std;
const int maxn = 1e5 + 10;
const int mod = 998244353;
void solve() {
	string str;
	cin >> str;
	int ans = 0;
	int x = 0;
	int lst = -1;
	for (auto ch : str) {
		if (ch - '0' <= lst) x = 0;
		lst = ch - '0';
		x |= 1 << (ch - '0'); 
		if (ch == '9') {
			if (__builtin_popcount(x) == 9) {
				ans += 10;
			} else ans += 4;
			x = 0;
		} 
	}
	cout << ans << "\n";
}
signed main() {
	ios::sync_with_stdio(0),cin.tie(0), cout.tie(0);
	int t = 1;
	// cin >> t;
	while (t--) solve();
	return 0; 
}

D.图不灵测试

进制转换,特判负数负号

#include<bits/stdc++.h>
#define int long long
#define pii piar<int, int>
#define db double 
using namespace std;
const int maxn = 1e5 + 10;
const int mod = 998244353;
int trans(char ch) {
	if (isdigit(ch)) return ch - '0';
	else {
		return 10 + ch - 'a';
	}
}
char trans2(int x) {
	if (x <= 9) return '0' + x;
	else return 'a' + x - 10;
}
void solve() {
	string a, b; cin >> a >> b;
	int aa = 0, bb = 0;
	for (auto ch : a) {
		aa = aa * 16 + trans(ch);
	}
	for (auto ch : b) {
		bb = bb * 16 + trans(ch);
	}
	int ans = aa - bb;
	int pos = ans >= 0;
	ans = abs(ans);
	if (pos == 0) cout << '-';
	string res;
	while (ans) {
		res.push_back(trans2(ans % 16));
		ans /= 16;
	}
	reverse(res.begin(), res.end());
	cout << res << "\n";
}
signed main() {
	ios::sync_with_stdio(0),cin.tie(0), cout.tie(0);
	int t = 1;
	// cin >> t;
	while (t--) solve();
	return 0; 
}

E.小A的口算题卡

枚举进制,边遍历边取余,看余数是否为0

#include<bits/stdc++.h>
#define int long long
#define pii piar<int, int>
#define db double 
using namespace std;
const int maxn = 1e5 + 10;
const int mod = 998244353;
string str;
int trans(char ch) {
	if (isdigit(ch)) return ch - '0';
	return 10 + ch - 'A';
}
int ck(int x) {
	int res = 0;
	for (auto ch : str) {
		res = (res * x + trans(ch)) % (x - 1);
	}
	return res == 0;
}
void solve() {
	cin >> str;
	int mx = 1;
	for (auto ch : str) {
		mx = max(mx, trans(ch) + 1);
	}
	for (int i = mx; i <= 36; i++) {
		if (ck(i)) {
			cout << i << "\n";
			return;
		}
	}
	cout << "No Solution\n";
}
signed main() {
	ios::sync_with_stdio(0),cin.tie(0), cout.tie(0);
	int t = 1;
	// cin >> t;
	while (t--) solve();
	return 0; 
}

F.贴纸导购

结论,题目等价于求差分数组的区间平均值最大值,即为差分数组的区间最大值,答案一定是相邻的两天买入卖出,遍历取最大值即可。

#include<bits/stdc++.h>
#define int long long
#define pii piar<int, int>
#define db double 
using namespace std;
const int maxn = 1e5 + 10;
const int mod = 998244353;
int arr[maxn];
void solve() {
	int n; cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> arr[i];
	}
	db ans = 0;
	for (int i = 2; i <= n; i++)
		ans = max(ans, (db)arr[i] - arr[i - 1]);
	printf("%.5f\n", ans);
}
signed main() {
//	ios::sync_with_stdio(0),cin.tie(0), cout.tie(0);
	int t = 1;
	// cin >> t;
	while (t--) solve();
	return 0; 
}

G.谁是非酋

交互题,随机选10个位置问是否是众数,可有不低于 \(1 - \frac{1}{2^{10}}\) 概率正确,关闭同步流的话注意用endl刷新缓冲区。

#include<bits/stdc++.h>
#define int long long
#define pii piar<int, int>
#define db double 
using namespace std;
const int maxn = 1e5 + 10;
const int mod = 998244353;
int query1(int x) {
	cout << "? 1 " << x << endl;
	int res; cin >> res; return res;
}
int query2(int x) {
	cout << "? 2 " << x << endl;
	int res; cin >> res; return res;
}
void solve() {
	int n; cin >> n;
	srand(time(0));
	for (int i = 1; i <= 10; i++) {
		int pos = rand() % n + 1;
		int tem = query1(pos);
		if (query2(tem)) {
			cout << "! " << tem << endl;
			return;
		}
	}
}
signed main() {
	ios::sync_with_stdio(0),cin.tie(0), cout.tie(0);
	int t = 1;
	// cin >> t;
	while (t--) solve();
	return 0; 
}

H.矩阵判断器

方法1 生成 \(1 \times n\) 的行向量 \(X\) 判断 \(X \times A \times B\) 是否等于 \(X \times C\) , 复杂度 \(O(n^2)\)

#include <bits/stdc++.h>
#define int long long
#define inf 0x3f3f3f3f
#define ll long long
#define pii pair<int, int>
#define tii tuple<int, int, int>
#define db double
#define all(a) a.begin(), a.end()
using namespace std;
const int maxn = 1e3 + 10;
const int mod = 998244353;
struct mat {
    vector<vector<int>> arr;
};
mat operator* (mat a, mat b) {
    int n = a.arr.size(), m = b.arr[0].size();
    vector<vector<int>> res(n, vector<int>(m));
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++) {
            for (int k = 0; k < a.arr[0].size(); k++)
                res[i][j] += a.arr[i][k] * b.arr[k][j];
        }
    return mat{res};
}
bool operator==(mat a, mat b) {
    return a.arr == b.arr;
}
void solve() {
    int n; cin >> n;
    mat A, B, C;
    A.arr.resize(n);
    for (int i = 0; i < n; i++) {
        A.arr[i].resize(n);
        for (int j = 0; j < n; j++)
            cin >> A.arr[i][j];
    }
    B.arr.resize(n);
    for (int i = 0; i < n; i++) {
        B.arr[i].resize(n);
        for (int j = 0; j < n; j++)
            cin >> B.arr[i][j];
    }
    C.arr.resize(n);
    for (int i = 0; i < n; i++) {
        C.arr[i].resize(n);
        for (int j = 0; j < n; j++)
            cin >> C.arr[i][j];
    }
    int flag = 1;
    srand(time(0));
    for (int i = 0; i < 2; i++) {
        vector<int> tem;
        for (int j = 0; j < n; j++)
            tem.push_back(rand() % 1000);
        mat tem2;
        tem2.arr.clear();
        tem2.arr.push_back(tem);
        flag &= (tem2 * A * B) == (tem2 * C);
        if (!flag) break;
    }
    cout << (flag ? "Yes" : "No") << "\n";
}
signed main() {
    // freopen("1.in", "r", stdin);
    // freopen("1.out", "w", stdout);
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int t = 1;
    cin >> t;
    while (t--) solve();
    return 0;
}

方法2 对于 \(C\) 的每一行求和,利用前缀和,快速算出 \(A \times B\) 对应的一行和,判断是否相等,对每一行计算,复杂度 \(O(n^2)\)

#include<bits/stdc++.h>
//#define int long long
#define ll long long
#define pii piar<int, int>
#define db double 
using namespace std;
const int maxn = 1e3 + 10;
const int mod = 998244353;
int a[maxn][maxn], b[maxn][maxn], c[maxn][maxn];
int sumb[maxn];
void solve() {
	int n; cin >> n;
	for (int i = 1; i <= n; i++)
		sumb[i] = 0;
	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], sumb[i] += b[i][j];	
	}
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
		 	cin >> c[i][j];
	for (int i = 1; i <= n; i++) {
		ll sumc = 0;
		for (int j = 1; j <= n; j++)
			sumc = (sumc + 1ll * c[i][j] + mod) % mod;
		ll sum = 0;
		for (int j = 1; j <= n; j++)
			sum = (sum + 1ll * a[i][j] * sumb[j] % mod + mod) % mod;
		if (sum != sumc) {
			cout << "No\n";
			return;
		}
	}
	cout << "Yes\n";
}
signed main() {
	ios::sync_with_stdio(0),cin.tie(0), cout.tie(0);
	int t = 1;
	 cin >> t;
	while (t--) solve();
	return 0; 
}

I.树织

预处理每一行的合法染色方案,爆搜枚举每一行的染色结果,最后判断列是否合法。

// 一眼鉴定为张老板出的题 
#include<bits/stdc++.h>
#define int long long
#define pii piar<int, int>
#define db double 
using namespace std;
const int maxn = 1e5 + 10;
const int mod = 998244353;
int n;
vector<int> vec[10];
vector<int> col[10];
int arr[10][10];
int ck() {
	for (int j = 0; j < n; j++) {
		vector<int> tem;
		for (int i = 0; i < n; i++) {
			if (arr[i][j] == 0) continue;
			int cnt = 0;
			while (i < n && arr[i][j] == 1) cnt++, i++;
			tem.push_back(cnt);
		}
		if (col[j] != tem) return 0;
	}
	return 1;
}
void dfs(int num, string str) {
	if (num == n - 1) {
//		if (str == "10220") {
//			for (int i = 0; i < n; i++)
//				for (int j = 0; j < n; j++)
//					cout << arr[i][j] << " \n"[j == n - 1];
//		}
		if (ck()) {
			for (int i = 0; i < n; i++)
				for (int j = 0; j < n; j++)
					cout << arr[i][j] << " \n"[j == n - 1];
			exit(0);
		}
		return;
	}
	for (int i = 0; i < vec[num + 1].size(); i++) {
		for (int k = (n - 1); k >= 0; k--)
			arr[num + 1][n - 1 - k] = vec[num + 1][i] >> k & 1;
		dfs(num + 1, str + (char)('0' + i));
	}
}
void solve() {
	cin >> n;
	for (int i = 0; i < n; i++) {
		int cnt; cin >> cnt;
		vector<int> tem;
		while (cnt--) {
			int x; cin >> x;
			tem.push_back(x);
		}
		for (int j = 0; j < (1 << n); j++) {
			vector<int> tem2;
			for (int k = (n - 1); k >= 0; k--) {
				if (!(j >> k & 1)) continue;
				int len = 0;
				while (k >= 0 && (j >> k & 1)) len++, k--;
				tem2.push_back(len);
			}
			if (tem2 == tem) {
				vec[i].push_back(j);
//				cout << i << " " << j << "\n";
			}
		}
	}
	for (int i = 0; i < n; i++) {
		int cnt; cin >> cnt;
		while (cnt--) {
			int x; cin >> x;
			col[i].push_back(x);
		}
	}
	for (int i = 0; i < vec[0].size(); i++) {
		for (int k = (n - 1); k >= 0; k--)
			arr[0][n - 1 - k] = vec[0][i] >> k & 1;
		dfs(0, to_string(i));
	}
	cout << "No solution.\n";
}
signed main() {
	ios::sync_with_stdio(0),cin.tie(0), cout.tie(0);
	int t = 1;
	// cin >> t;
	while (t--) solve();
	return 0; 
}

J.小L的游戏

图论建模, 对于 \(x - y\) 看作一个节点, 每个操作看作一条移动 \(a - b\) 或 \(b - a\) 的长度为 \(c\) 的边, 跑最短路。建边时注意先去重取最短的边,再跑迪杰斯特拉,负数下标整体偏移 \(2\times 10^3\)。

#include<bits/stdc++.h>
#define int long long
#define pii pair<int, int>
#define db double 
using namespace std;
const int maxn = 1e5 + 10;
const int mod = 998244353;
vector<pii> G[maxn]; 
int vis[maxn], dis[maxn];
map<int, int> mp;
const int base = 2e3;
void solve() {
	int x, y; cin >> x >> y;
	int L, R; cin >> L >> R;
	int n, m; cin >> n >> m;
	if (x - y < L || x - y > R) {
		cout << 2147483647 << "\n";
		return;
	}
	L += base, R += base;
	int s = x - y + base;
	for (int i = 1; i <= n; i++) {
		int a, b, c; cin >> a >> b >> c;
		for (auto it : {a - b, b - a}) {
			if (!mp.count(it)) {
				mp[it] = c;
			} else mp[it] = min(mp[it], c);
		}
	}
	for (int i = L; i <= R; i++) {
		for (auto [u, v] : mp) {
			if (L <= i + u && i + u <= R) {
				G[i].emplace_back(i + u, v);
			}
		}
	}
	priority_queue<pii, vector<pii>, greater<pii>> q;
	memset(dis, 0x3f, sizeof dis);
	dis[s] = 0;
	q.push(pii{0, s});
	while (!q.empty()) {
		int u = q.top().second;
		q.pop();
		if (vis[u]) continue;
		vis[u] = 1;
		for (auto [v, w] : G[u]) {
			if (dis[v] > dis[u] + w) {
				dis[v] = dis[u] + w;
				q.push(pii{dis[v], v});
			}
		}
	} 
	int ans = 2e18;
	for (auto t : {m + base, -m + base}) {
		if (L <= t && t <= R) {
			ans = min(ans, dis[t]);
		}
	}
	if (ans > 1e18) {
		cout << "2147483647\n";
	} else cout << ans << "\n";
}
signed main() {
	ios::sync_with_stdio(0),cin.tie(0), cout.tie(0);
	int t = 1;
	// cin >> t;
	while (t--) solve();
	return 0; 
}

K.DTOOTD

发现答案为YES等价于可以将字符串划为两个非回文串, 考虑预处理数组 \(pre[i]\) 和 \(suf[i]\) 表示每个前缀和后缀是否是回文串, 可以使用哈希、马拉车,PAM。
哈希做法对正串和反串处理哈希值, 每次 \(O(1)\) 判断子串是否是回文串。

#include<bits/stdc++.h>
#define int long long
#define ll __int128_t
#define pii piar<int, int>
#define db double 
using namespace std;
const int maxn = 1e6 + 10;
const int mod = 1e18 + 121, base = 131;
int mi[maxn];
int h[maxn], h2[maxn];
void init(string& str) {
	mi[0] = 1;
	int n = str.length();
	for (int i = 1; i <= n; i++)
		mi[i] = (ll)mi[i - 1] * base % mod;
	for (int i = 1; i <= n; i++) {
		h[i] = ((ll)h[i - 1] * base + str[i - 1]) % mod;
		h2[i] = ((ll)h2[i - 1] * base + str[n - i]) % mod;
	}
}
int query(int l, int r, int h1[]) {
	return (h1[r] - (ll)h1[l - 1] * mi[r - l + 1] % mod + mod) % mod;
}
int n;
int ishuiwen(int l, int r) {
//	cout << query(l, r, h) << "\n";
//	cout <<  query(n - r + 1, n - l + 1, h2) << "\n";
	return query(l, r, h) == query(n - r + 1, n - l + 1, h2);
}
void solve() {
	string str; cin >> str;
	init(str);
	set<char> s;
	for (auto ch : str) {
		s.insert(ch);
	}
	if (s.size() == 1) {
		cout << "NO\n";
		return;
	}
	n = str.length();
	int flag = ishuiwen(1, n);
	if (!flag) {
		cout << "YES\n1\n" << str << "\n";
		return;
	}
	for (int i = 2; i <= n; i++) {
		if (!ishuiwen(1, i - 1) && !ishuiwen(i, n)) {
			cout << "YES\n2\n";
			cout << str.substr(0, i - 1) << " " << str.substr(i - 1) << "\n";
			return;
		}
	}
	cout << "NO\n";
}
signed main() {
	ios::sync_with_stdio(0),cin.tie(0), cout.tie(0);
	int t = 1;
	 cin >> t;
	while (t--) solve();
	return 0; 
}

马拉车做法枚举每个前缀,看中心的最长回文半径是否覆盖到端点,代码略。

PAM做法,边插入字符,边判断前缀的最长回文后缀是否覆盖到端点。插入后对于终点,不断跳fail指针,得到每个后缀是否是回文串。

#include <bits/stdc++.h>
// #define int long long
#define inf 0x3f3f3f3f
#define ll long long
#define pii pair<int, int>
#define tii tuple<int, int, int>
#define db double
#define all(a) a.begin(), a.end()
using namespace std;
const int maxn = 1e6 + 10;
const int mod = 998244353;
vector<pii> vec;
struct PAM {
    int tot, last, fail[maxn], c[maxn][26], len[maxn];
    char s[maxn];  // 下标从1开始的字符串
    PAM() {
        tot = last = fail[0] = 1, len[1] = -1, len[0] = 0;
    }
    void clear() {
        for (auto it : vec) {
            c[it.first][it.second] = 0;
        }
        vec.clear();
        tot = last = fail[0] = 1, len[1] = -1, len[0] = 0;
    }
    int getfail(int x, int i) {
        while (s[i - len[x] - 1] != s[i])
            x = fail[x];
        return x;
    }
    void extend(char ch, int i) {  // 插入位置 i 的字符 ch
        s[i] = ch;
        int x = getfail(last, i), v = ch - 'a';
        if (!c[x][v]) {
            len[++tot] = len[x] + 2;
            int tem = getfail(fail[x], i);
            fail[tot] = c[tem][v];
            c[x][v] = tot;  // 必须放最后
            vec.emplace_back(x, v);
        }
        last = c[x][v];
    }
} pam;
int pre[maxn], suf[maxn];
void solve() {
    pam.clear();
    string str; cin >> str;
    int n = str.length();
    for (int i = 1; i <= n; i++) pre[i] = suf[i] = 0;
    for (int i = 1; i <= n; i++) {
        pam.extend(str[i - 1], i);
        if (pam.len[pam.last] == i) pre[i] = 1;
    }
    int x = pam.last;
    while (x > 1) {
        suf[n - pam.len[x] + 1] = 1;
        x = pam.fail[x];
    }
    if (!pre[n]) {
        cout << "YES\n1\n" << str << "\n";
        return;
    }
    for (int i = 1; i < n; i++)
        if (!pre[i] && !suf[i + 1]) {
            cout << "YES\n2\n" << str.substr(0, i) << " " << str.substr(i, n - i + 1) << "\n";
            return;
        }
    cout << "NO\n";
}
signed main() {
    // freopen("1.in", "r", stdin);
    // freopen("1.out", "w", stdout);
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int t = 1;
    cin >> t;
    while (t--) solve();
    return 0;
}

标签:arr,return,int,题解,long,2024,maxn,天津大学,define
From: https://www.cnblogs.com/TJUHuangTao/p/18623682

相关文章

  • 【2024-12-21】连岳摘抄
    23:59寒夜客来茶当酒,竹炉汤沸火初红。寻常一样窗前月,才有梅花便不同。                                                 ——《寒夜》宋·杜耒学了辩证法,你不会害怕......
  • 2024/12/23
    好像应该是看文献,应用方法,做实验,看效果,改实验而不是全部都看好了,框架也想好了,然后着手开始写代码可是这些目前为止看的论文没有开源代码啊!可能复现代码就是学计算机的要有的一个看家本事。 2.如何寻找合适的代码在GitHub上找代码的技巧:搜索关键词:使用论文标题的一......
  • “用户满意品牌”——触想荣获CMCD 2024运动控制领域大奖
    12月12日,2024CMCD运动控制及CDDIA直驱领域年度颁奖盛典在深圳召开,触想受邀出席并获得“CMCD2024年度运动控制领域‘用户满意品牌’”奖,再次彰显触想对技术创新与产品性能的不懈追求。△触想获CMCD2024“用户满意品牌”奖2024CMCD奖是工控领域重要活动之一,汇聚......
  • 2024.12.22 周日
    2024.12.22周日Q1.1100Youareplayingacomputergame.Thecurrentlevelofthisgamecanbemodeledasastraightline.Yourcharacterisinpoint$0$ofthisline.Thereare$n$monsterstryingtokillyourcharacter;the$i$-thmonsterhashealthequ......
  • AT_keyence2019_e Connecting Cities 题解
    题目传送门前置知识Boruvka算法解法考虑Boruvka算法。拆掉绝对值后得到\(a_{i}+id,a_{i}-id,a_{j}+id,a_{j}-id\)四个式子。vector启发式合并辅助线段树查询的常数过大,无法通过。上述做法的常数在于一条边会被计算两次,考虑优化。不妨直接钦定向前连、向后连的贡献,顺......
  • .net framework 4.7.2 winform框架项目升级到.net 8.0项目 界面比列失调问题解决
    一、问题发生前:在.netframework4.7.2winform框架开发的项目之前在.netframework4.7.2开发的winform项目,在visualstudio一打开的时候,虽然界面内有些控件也会失调,但是他会提示“使用100%缩放比例重新启动VisualStudio”点击“使用100%缩放比例重新启动VisualStudio”......
  • 【2024-12-20】天生好习惯
    20:00每一天都是一小段生命。                                                 ——叔本华今天中午跟同事一起聚餐时,聊起了她们家的小女儿爱于净、爱收拾的好习惯,说她......
  • 【2024最新】渗透测试工具大全(超详细),收藏这一篇就够了!
     黑客/网安大礼包:......
  • 【2024最新】渗透测试工具大全(超详细),收藏这一篇就够了!
     黑客/网安大礼包:......
  • 题解 - 换位置游戏
    题目描述N个小朋友(编号为1到N)正在玩一个换位置游戏。从左到右依次排列着N个凳子(编号为1到N,最左边的为1号凳子,最右边的为N号凳子),每个凳子上都有一个数字(凳脚处红色数字),每个数字互不相同,且都是不超过N的正整数。游戏开始前,1号小朋友坐在1号凳子上,2号小......