百度历年秋招笔试真题
如需获取完整资料,请点击下方链接领取《2024校招笔试真题秘籍》(实时更新中)
不收费,3人组团即可一块免费领取!限量免费10000个名额
手机端点击免费领取:https://www.nowcoder.com/link/campus_xzbs2
电脑端请扫码领取:
1、混战世界
【题目描述】战乱年代,整个世界各个军阀的兵团混战,你是PZ军团的战略参谋,你手下有n(保证为3的倍数)个士兵,第i个士兵的物理攻击数值为Ai,魔 法攻击数值为Bi,你需要将这些士兵三等分为三个连,第一个连需要去物理空间参加物理对抗战争,战斗力估值W1为士兵的物理攻击数值之 和;第二个连需要去魔法空间参加魔法对抗战争,战斗力估值W2为士兵的魔法攻击数值之和;第三个连需要去虚幻空间参加物理魔法兼备的综 合对抗战争,战斗力估值W3为所有士兵的物理攻击数值、魔法攻击数值之和除以2。你希望W1+W2+W3最大,这样才最有可能胜利。
输入描述:
第一行一个整数n,保证为3的倍数。(3≤n≤100000) 第二行n个整数,第i个数表示Ai。 第三行n个整数,第i个数表示Bi。(1≤Ai, Bi≤1000)
输出描述:
一个小数,表示最大数值和,保留两位小数(四舍五入)。
输入样例:
6
1 7 3 4 5 9
2 3 9 4 3 3
输出样例:
35.00
【解题思路】
设一个人的物理值为A,魔法值为B。
派去一连可得A的贡献,二连可得(A+B)/2,三连可得B。
去一连与去二连相比差了A-(A+B)/2 = (A-B)/2,同理,去二连比去三连也差了(A-B)/2。
这样,可以根据每个人的A-B数值进行排序,较大者去一连,较小者去三连,中间的去二连。
【参考代码】
#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
int a[N], b[N], id[N], n;
inline bool cmp(int x, int y) {
return a[x] - b[x] > a[y] - b[y];
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i)
scanf("%d", a + i);
for (int i = 1; i <= n; ++i)
scanf("%d", b + i);
for (int i = 1; i <= n; ++i)
id[i] = i;
sort(id + 1, id + n + 1, cmp);
int k = n / 3;
long long ans = 0;
for (int i = 1; i <= n; ++i) {
if (i <= k) ans += a[id[i]] * 2;
else if (i <= k * 2) ans += a[id[i]] + b[id[i]];
else ans += b[id[i]] * 2;
}
printf("%.2f\n", ans / 2.0);
return 0;
}
2、字符串计数
【题目描述】给定一个仅由小写字母组成且长度不超过106的字符串,将首字符移到末尾并记录所得的字符串,不断重复该操作,虽然记录了无限个字符串, 但其中不同字符串的数目却是有限的,那么一共记录了多少个不同的字符串?
输入描述:
输入给定的字符串。
输出描述:
输出记录的不同字符串的数目。
输入样例:
abab
输出样例:
2
【解题思路】
利用kmp算法的next数组,可以求出字符串的最小循环周期T,这就是答案。
也可以将字符串在后面复制一次,用字符串hash和std::map统计。
【参考代码】
#include <bits/stdc++.h>
#define N 1000007
using namespace std;
char s[N];
int nxt[N];
int main() {
scanf("%s",s);
int n=strlen(s);
nxt[0]=-1;
for(int i=0,j=-1; i<n;)
if(j==-1 || s[i]==s[j])nxt[++i]=++j;
else j=nxt[j];
if(n%(n-nxt[n]))printf("%d",n);
else printf("%d",n-nxt[n]);
}
3、表兄弟
【题目描述】每个人的家族关系可以表示成为一棵树,显而易见,家族关系中不会有环的存在。 假设家族关系树中的每条边的权值都为1, 我们称x是y的k祖先,当且仅当在家族关系树中x是y的祖先且x到y的距离是k。 我们称x和y为k表兄弟,当且仅当x和y的k祖先为同一人。 现在给出一个家族关系,共有n个家族成员,因为历史记录的缺失,所有可能并不知道有些人的父亲是谁(最后的结果可能是 若干个树),给出m个询问,每个询问包含一个x和一个k,请你找出x成员的k表兄弟的数量。
输入描述:
输入第一行是一个整数n(1≤n≤105)表示家族关系树中成员数量。 第二行有n个数,中间用空格隔开,第i个数fi表示i号成员的父亲为fi,如果fi为0,表示不知道i号成员父亲是谁。 第三行包含一个整数m(1≤m≤105) ,表示询问的数量。 接下来有m行,每行有两个正整数x,k,中间用空格隔开,表示询问x成员的k表兄弟有多少个。
输出描述:
对于每一个询问,输出一个整数,表示x成员的k表兄弟数量,中间用空格隔开。
输入样例:
10
0 1 2 0 1 5 6 3 3 0
1 0
9 1
5 4
2 2
10 1
8 4
7 1
3 2
5 2
4 2
3 1
输出样例:
1 0 0 0 0 0 1 0 0 0
【解题思路】
利用倍增法可以在O(logn)的时间内找到u点的k祖先anc。
问题转化为求anc的所有k后代。
可以先求出这个森林的dfs序,然后将同一深度的点存到一个std::vector中。
对于一个祖先anc,在深度为dep[u]的vector中二分查找in[anc]和out[anc],即可求得所有的k后代,减去u本身就是u的k表兄弟数量。
【参考代码】
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+20;
vector <int> v[N],d[N];
int n,m,pa[N],par[N][23],h[N],st[N],fi[N],x1,y2,x,y,p,cnt=0;
void dfs(int s) {
int y;
st[s]=++cnt;
d[h[s]].push_back(st[s]);
for(int i=0; i<v[s].size(); i++) {
y=v[s][i];
h[y]=h[s]+1;
dfs(y);
}
fi[s]=cnt;
}
int main() {
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin >> n;
for(int i=1; i<=n; i++) {
cin >> pa[i];
if(pa[i]!=0) {
v[pa[i]].push_back(i);
par[i][0]=pa[i];
} else
par[i][0]=i;
}
cnt=0;
for(int i=1; i<=n; i++) {
if(pa[i]==0) {
h[i]=0;
dfs(i);
}
}
for(int i=1; i<=20; i++) {
for(int j=1; j<=n; j++) {
par[j][i]=par[par[j][i-1]][i-1];
}
}
cin >> m;
for(int i=1; i<=m; i++) {
cin >> x >> p;
y=x;
for(int j=20; j>=0; j--)
if(p & (1<<j))
y=par[y][j];
if(h[x]-p<0) {
cout << 0 << ' ';
continue;
}
x1=st[y];
y2=fi[y];
x1=lower_bound(d[h[x]].begin(),d[h[x]].end(),x1)-d[h[x]].begin();
y2=upper_bound(d[h[x]].begin(),d[h[x]].end(),y2)-d[h[x]].b
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
本专刊由牛客官方团队打造,主要讲解名企校招技术岗位的笔试题,内容中包含多个名企的笔试真题,附有题目思路及参考代码