目录
前言
苏州是个很美的城市,苏州大学是一所很美的大学~
可惜自己能力不够,做了大概50-60分的题吧,基本上寄了,其实下来自己复刻代码感觉用不了2个小时就能写完,考场旁边的大哥做的飞快而且是考场第一个AK的,让我心态也很爆炸,基本上最后一小时啥也没干,道阻且长,继续努力吧。
机房中编程环境详见
1)C/C++编程环境为:visual studio 2010;
2)Python编程环境:python3.7, IDE: IDLE;
3)Java编程环境:Eclipse。
赛时为 pdf文件*1, sample.cpp文件*1。每个题对应一个sample文件中的函数,如第一题func1()。需要在vs 2010下运行成功该函数。vs 2010 版本可能为C++ 98,无C++11特性如auto,匿名函数等,且并不允许代码中出现类似cout,printf的出现。
题型并不类似于编程竞赛,更类似于leetcode,推荐leetcode Hot100进行练习。链接如下:
题单 - 力扣(LeetCode)全球极客挚爱的技术成长平台
需要注意!
1. 本代码为补题代码,仅具有参考价值,并不保证样例、题目正确,只能保证相似,且并没有大样例!
2. 如有错误请心平气和指出,本人非常fw && C++98与平时代码编写不同,做不到赛时ak
3. 为方便输入输出样例,采用多组样例输入,原题并不存在该输入输出
一、程序设计题目(6道,每道60分)
1.1 判断格子
题目:输入一个位置,如果是黑色返回True,白色返回False
输入样例:
3
a1
g6
h8
输出样例:
True
False
True
题解:
a~h映射为1~8,相加为偶数 return True,奇数 return False
bool func1(const string &str)
{
int a = str[0] - 'a' + 1;
int b = str[1] - '0' + 1;
if(a + b & 1) return true;
else return false;
}
测试代码:
#include<bits/stdc++.h>
using namespace std;
bool func1(const string &str)
{
int a = str[0] - 'a' + 1;
int b = str[1] - '0' + 1;
if(a + b & 1) return true;
else return false;
}
void solve()
{
string str;
cin >> str;
if(func1(str)) puts("True");
else puts("False");
}
int main() {
int t;
cin >> t;
while(t --)
solve();
system("pause");
return 0;
}
1.2 相差几天
题目:给定两个非负向量,每个向量分别存年,月,日,完成代码,计算差几天
年合法,范围是1~3000,且月和日期可能不合法,且日期取前闭后开,如[2024,8,21]与[2024,8,22]相差一天。保证前向量永远小于后向量。
题解:计算两个向量分别到1年1日,然后相减即可,注意闰月。
输入样例(不是原本的样例):
3
2000 1 1
2000 3 1
1999 2 29
1999 3 1
2000 1 1
2024 1 1
输出样例:
60
-1
8766
#include <bits/stdc++.h>
using namespace std;
bool check(int year) {
if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
return true;
else
return false;
}
int func2(const vector<int> &v1, const vector<int> &v2) {
int y1 = v1[0], m1 = v1[1], d1 = v1[2];
int y2 = v2[0], m2 = v2[1], d2 = v2[2];
int lu_d[13] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int d[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int sum_lu_d[13] = {0};
int sum_d[13] = {0};
for (int i = 1; i <= 12; i++) {
sum_lu_d[i] = sum_lu_d[i - 1] + lu_d[i];
sum_d[i] = sum_d[i - 1] + d[i];
}
bool l_y1 = check(y1);
bool l_y2 = check(y2);
if (l_y1) {
if (m1 < 1 || m1 > 12) return -1;
if (d1 < 1 || d1 > lu_d[m1]) return -1;
} else {
if (m1 < 1 || m1 > 12) return -1;
if (d1 < 1 || d1 > d[m1]) return -1;
}
if (l_y2) {
if (m2 < 1 || m2 > 12) return -1;
if (d2 < 1 || d2 > lu_d[m2]) return -1;
} else {
if (m2 < 1 || m2 > 12) return -1;
if (d2 < 1 || d2 > d[m2]) return -1;
}
int sum1 = 0, sum2 = 0;
for (int i = 1; i < y1; i++) {
sum1 += check(i) ? 366 : 365;
}
for (int i = 1; i < y2; i++) {
sum2 += check(i) ? 366 : 365;
}
sum1 += l_y1 ? sum_lu_d[m1 - 1] + d1 : sum_d[m1 - 1] + d1;
sum2 += l_y2 ? sum_lu_d[m2 - 1] + d2 : sum_d[m2 - 1] + d2;
return sum2 - sum1;
}
void solve() {
vector<int> v1(3), v2(3);
for (int &x : v1) cin >> x;
for (int &x : v2) cin >> x;
cout << func2(v1, v2) << endl;
}
int main() {
int t;
cin >> t;
while (t--)
solve();
system("pause");
return 0;
}
1.3 存钱
题目:小明第一天存一元,然后接下来两天每天存2元,再接下来三天每天存3元,按照该规律,到第n天能存多少钱
题解:根据题意即可。
输入样例(不是原本的样例):
3
4
6
365
输出样例:
8
14
6579
#include <bits/stdc++.h>
using namespace std;
int func3(int n)
{
int total = 0; // 总存款金额
int day_count = 0; // 记录已经过去的天数
int k = 1; // 当前存款金额和持续天数
while (day_count < n) {
int days_to_add = min(k, n - day_count); // 计算当前金额k需要存的天数
total += days_to_add * k; // 累加金额
day_count += days_to_add; // 更新已过去的天数
k++; // 下一个阶段
}
return total;
}
void solve()
{
int n;
cin >> n;
cout << func3(n) << endl;
}
int main() {
int t;
cin >> t;
while (t--)
solve();
return 0;
}
1.4 相似单词匹配
题目:只有英文字母,忽略大小写,格式如下的类似单词判断是否一致,一致输出1,不一致输出0,长度不同输出-1.
例如'egg'与'bee'一致,'good'与‘food'一致。
题解:很多种方法,也有很多优化,纯暴力就可以。
#include <bits/stdc++.h>
using namespace std;
int func4(const string &s1, const string &s2) {
if(s1.size() != s2.size())
return -1;
unordered_map<char, vector<int>> mp1, mp2;
for(int i = 0; i < s1.size(); i ++)
{
mp1[s1[i]].push_back(i);
mp2[s2[i]].push_back(i);
}
for(int i = 0; i < s1.size(); i ++)
{
if(mp1[s1[i]] == mp2[s2[i]]) continue;
else return 0;
}
return 1;
}
void solve() {
string s1, s2;
cin >> s1 >> s2;
cout << func4(s1, s2) << endl;
}
int main() {
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
1.5 旋转图像
为参考链接的改题:. - 力扣(LeetCode)
题目:输入-1时向右旋转90°,输入1时向左旋转90°,输入2是转置矩阵,输出其他数直接输出该矩阵。
输入样例(不是原本的样例):
3
1
3 3
1 2 3
4 5 6
7 8 9
2
3 3
1 2 3
4 5 6
7 8 9
-1
3 3
1 2 3
4 5 6
7 8 9
5
3 3
1 2 3
4 5 6
7 8 9
输出样例:
7 4 1
8 5 2
9 6 33 6 9
2 5 8
1 4 71 4 7
2 5 8
3 6 9
1 2 3
4 5 6
7 8 9
题解:
此题注意vector操作。
右旋转时,原图第一行,成为旋转后的最后一列,因此列变行,行做列对称。
左旋转时,原图第一行,成为旋转后的第一列,因此行变列,列作行对称。
转置矩阵是中心对称的,变换横纵坐标。
代码:
#include <bits/stdc++.h>
using namespace std;
vector<vector<int>> func5(vector<vector<int>> &matrix, int flag) {
int rows = matrix.size();
int cols = matrix[0].size();
vector<vector<int>> result;
if (flag == -1) {
// 右旋转90度
result.resize(cols, vector<int>(rows));
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
result[j][rows - 1 - i] = matrix[i][j];
}
}
} else if (flag == 1) {
// 左旋转90度
result.resize(cols, vector<int>(rows));
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
result[cols - 1 - j][i] = matrix[i][j];
}
}
} else if (flag == 2) {
// 转置矩阵
result.resize(cols, vector<int>(rows));
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
result[j][i] = matrix[i][j];
}
}
}
else {
// 直接输出原矩阵
result = matrix;
}
return result;
}
void solve() {
int flag;
cin >> flag;
int rows, cols;
cin >> rows >> cols;
vector<vector<int>> matrix(rows, vector<int>(cols));
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
cin >> matrix[i][j];
}
}
vector<vector<int>> result = func5(matrix, flag);
for (const auto &row : result) {
for (const auto &elem : row) {
cout << elem << " ";
}
cout << endl;
}
}
int main() {
int t;
cin >> t;
while (t--)
solve();
system("pause");
return 0;
}
1.6 判断2的幂
题目:对一个不超过unsigned int的数,判断是不是2的幂次,本题不再给样例。
题解:有很多方法,最简单的如代码所示:
#include <bits/stdc++.h>
using namespace std;
bool func6(unsigned int x) {
return x > 0 && (x & (x - 1)) == 0;
}
void solve()
{
unsigned int n;
cin >> n;
cout << func6(n) << endl;
}
int main() {
int t;
cin >> t;
while(t -- )
solve();
system("pause");
return 0;
}
二、数据结构题(2道,每道20分)
2.1 反转链表(此题后续再补,无源码)
给定链表类构建代码,需要完成该类下函数代码的填充,并且不能修改任何函数,以及传参
1.将一段指针翻转,如输出的为1->2->3->4->6->5->7->8,如果反转从m = 2到x = 6的段落(头节点不计数),则反转后为1->5->6->4->3->2->7->8
2.如果m >= x,不反转
思路:感觉写起来很麻烦
2.2 二叉树找到仅大于target的值(此题后续再补,无源码)
给定二叉树类构建的代码,需要完成代码的填充,并且不能修改任何函数,以及传参
1.给定一个函数,输入一个值,然后去找到比这个树更大的值,且仅大于这个数的值。
思路:递归查找即可
三、算法题(2道,每道20分)
3.1 完全平方数
题目:力扣原题. - 力扣(LeetCode)
绷不住了,补题补一半突然发现自己wa了,突然发现这不一眼dp,为什么有nt拿贪心做啊
思路:线性dp,定义为背包容积为m时,采用的最少平方数个数
代码:
class Solution {
public:
int INF = 1e4 + 10;
int numSquares(int n) {
vector<int>dp(n + 1, INF);
dp[0] = 0;
for(int i = 1; i <= n; i ++)
for(int j = 1; j * j <= i; j ++)
dp[i] = std::min(dp[i], dp[i - j * j] + 1);
return dp[n];
}
};
3.2 错位排列
题目:n个人的有n个帽子,求排列,回不到自己手里的组合数,mod1e9 + 7(
题解:典型的错位排列问题,Wiki证明链接如下错位排列 - OI Wiki
B站非常好的一个递推证明如下:
全网最详细的全错排问题,学不会你找我_哔哩哔哩_bilibili
个人参考后证明如下:
输入样例(不是原本的样例):
5
1
2
3
4
5
输出样例:
1
2
9
44
265
#include <bits/stdc++.h>
using namespace std;
int func10(int n) {
int mod = 1e9 + 7;
vector<int>dp(n + 1, 0);
if (n == 0) return -1;
if (n == 1) return 0;
if (n == 2) return 1;
dp[0] = 1;
dp[1] = 0;
dp[2] = 1;
for (int i = 3; i <= n; i++) {
dp[i] = (i - 1) * ((dp[i - 1] + dp[i - 2]) % mod) % mod;
}
return dp[n];
}
void solve() {
int n;
cin >> n;
cout << func10(n) << endl;
}
int main() {
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
总结
如果不论交题方法的话,我个人认为绝大多数人能做到90分,所以我的苏大推免大抵是寄了。可能会卡到错排(其实样例也给你了,如果有心推也能把递推公式推出来)。这份保研试题难度不能说高,但是比天大杯考的更加全面,但是天大杯也更适合我,虽然tju也没要我(好像是我自己的问题),这份试卷也让我深刻意识到自己的数据结构不足,以后也会多做一些leetcode了QAQ