Contest ICT pFind
[TOC]
ICT pFind
机试:共五道,前两个签到,第三个大数乘法,第四个区间最值问题,第五个数据结构二叉树问题
机试-1
题目大意:将二维数组进行翻转
思路:储存在二维数组中,利用循环来进行翻转然后输出。
#include <iostream>
using namespace std;
const int maxn = 209;
int n, a[maxn][maxn];
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j)
scanf("%d", &a[i][j]);
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
printf("%d ", a[n-j+1][i]);
}
printf("\n");
}
return 0;
}
机试-2
题目大意:括号匹配,非左右括号的按照异常处理,然后查看左右括号是否匹配
思路:维护一个常量来标注左右括号
// 95
#include <iostream>
using namespace std;
string str;
int cnt = 0;
int main() {
cin>>str;
for (int i = 0; i < str.length(); ++i) {
if (str[i] == '(') cnt++;
else if (str[i] == ')') cnt--;
else {puts("NO");return 0;}
}
if (!cnt) puts("YES");
else puts("NO");
return 0;
}
机试-3
题目大意:查看某数的阶乘末尾有多少0
思路:大数乘法
#include <iostream>
using namespace std;
const int maxn = 1e5+9;
int a[maxn], lena, n;
int main() {
scanf("%d", &n);a[1] = 1;lena = 3000;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= lena; ++j)
a[j] *= i;
for (int j = 1; j <= lena; ++j)
if (a[j] > 10) a[j+1] += a[j]/10, a[j]%=10;
}
int flag = 1, ans = 0;
for (int i = 1; i <= lena; ++i) if (flag && !a[i]) ans++;else flag = 0;
printf("%d\n", ans);
}
机试-4
题目大意:找出数组最大子区间和
思路:维护一个tem变量,来判断下个元素是否要累加进来,如果下个元素加进来导致tem<0,那么就需要重置tem了,然后重新累加。
#include <iostream>
using namespace std;
const int maxn = 1e5+9;
int n, a[maxn], tem, ans;
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%d", a+i);
for (int i = 1; i <= n; ++i){
if (tem + a[i] < 0) tem = 0;
else tem += a[i], ans = max(ans, tem);}
printf("%d\n", ans);
return 0;
}
机试-5
题目大意:给出二叉树前中序遍历,得到后序遍历
思路:维护二叉链表,先建树,然后在后序遍历
#include <iostream>
using namespace std;
const int maxn = 1e5+9;
int n, pre[maxn], in[maxn];
struct node {
int val;
node * l, * r;
} *root;
// pre root-l-r in l-root-r => bg:pre, l/r:in
node * build(int bg, int l, int r) {
if (l > r) return NULL;
// 遍历查找根的位置
node * nw = new node();
for (int i = l; i <= r; ++i) {
if (pre[bg] == in[i]) {
// 找到分界点
nw->val = pre[bg];
nw->l = build(bg+1, l, i-1);
nw->r = build(bg+1+(i-l), i+1, r);
}
}
return nw;
}
// post l-r-root
void post_traverse(node * nw) {
if (nw->l) post_traverse(nw->l);
if (nw->r) post_traverse(nw->r);
printf("%d ", nw->val);
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%d", pre+i);
for (int i = 1; i <= n; ++i) scanf("%d", in+i);
root = build(1, 1, n);
post_traverse(root);
return 0;
}
笔试算法题:3个基础算法题+2个附加算法题
基础算法题1
题目:快排最好、最差、平均 各自的比较次数;快排最差情况举一个例子;复杂度分析
思路:
基础算法题2
题目:将数n拆成m个,求这m个数最大乘积是多少
思路:DFS+剪枝
基础算法题3
题目:给出一个数组,得到逆序对的个数
思路:归并排序途中计数
附加算法题1
题目:给一堆石子,然后每个人每次可以抽取1~m个,每个人都按照最优的方法抽取,最后一颗石子谁抽谁输。问是否有策略
思路:博弈论,巴士博弈的变式。巴士博弈是如果谁拿最后一颗石子谁赢。那么只要$n%(m+1)\ne0$ 那么先手必定赢,因为先手只需要保证每轮都是m+1个进行消耗即可;但是如果$n%(m+1)= 0$ 那么后手就可以保证每次都消耗m+1个,让最后先手抽的时候剩下m+1个,那么后手就必赢