【AI/算法类】OPPO 2025届秋招笔试题(B卷)

Iareges 2024-08-22 17:01:03 阅读 99

目录

1. 第一题2. 第二题3. 第三题

⏰ 时间:2024/08/10

🔄 输入输出:ACM格式

⏳ 时长:2h

本试卷还有选择题部分,但这部分比较简单就不再展示。

1. 第一题

小O有一个正整数

x

x

x,他想知道,第一个不小于

x

x

x 的素数是几,请你帮帮他吧。

输入描述

输入包含一行一个正整数

x

(

1

<

x

<

1

0

8

)

x\,(1<x< 10^8)

x(1<x<108),表示小O拥有的正整数。

输出描述

输出包含一行一个正整数,表示不小于

x

x

x 的最小素数。

题解

暴力遍历即可。

<code>#include <bits/stdc++.h>

using namespace std;

bool isPrime(int n) { -- -->

if (n <= 1) return false;

if (n <= 3) return true;

if (n % 2 == 0 || n % 3 == 0) return false;

for (int i = 5; i * i <= n; i += 6) {

if (n % i == 0 || n % (i + 2) == 0) return false;

}

return true;

}

int main() {

int x;

cin >> x;

while (!isPrime(x)) {

x++;

}

cout << x << endl;

return 0;

}

2. 第二题

小O面前有

n

n

n 堆糖果,编号从

1

1

1 到

n

n

n,Alice和Bob将轮流拿走编号最小的糖果堆中的所有糖果,具体的:Alice 首先会拿走第一堆,然后Bob拿走第二堆,然后Alice拿走第三堆…直到

n

n

n 堆糖果全都被拿完为止。

小O现在希望 Alice 和 Bob 两人的糖果数量之差尽可能小(即如果Alice糖果数量为

x

x

x, Bob糖果数量为

y

y

y,他想使得

x

y

|x-y|

∣x−y∣ 的值尽可能小),为此他可以最多提前拿走一堆糖果(当然拿走后,位于这堆糖果之后的所有糖果编号也会减一)。

请你帮他求出这个最小值吧。

输入描述

第一行输入一个整数

n

(

1

n

2

1

0

5

)

n\,(1\leq n\leq 2\cdot 10^5)

n(1≤n≤2⋅105) 代表糖果的堆数。

第二行输入

n

n

n 个整数

a

1

,

a

2

,

.

.

.

,

a

n

(

1

a

i

1

0

9

)

a_1,a_2,...,a_n\,(1\leq a_i\leq10^9)

a1​,a2​,...,an​(1≤ai​≤109) 代表每一堆糖果的数量。

输出描述

在一行上输出一个整数,代表两人糖果数量之差的最小值。

题解

在小O拿走之前,Alice的序列是1、3、5、7等,为奇数序列,Bob的序列是2、4、6、8等,为偶数序列。

考虑一个

n

=

9

n=9

n=9 的简单情形,假设小O拿走第

5

5

5 个,那么剩下的糖果堆为

12346789

1 2 3 4 6 7 8 9

12346789,Alice的序列为

1368

1 3 6 8

1368,Bob的序列为

2479

2 4 7 9

2479,可以发现,以

5

5

5 为分界点,Alice的序列中

5

5

5 左边的取的都是奇数,

5

5

5 右边的都是偶数。Bob序列中

5

5

5 左边的都是偶数,

5

5

5 右边的都是奇数。即无论是Alice还是Bob,位于分界点两边的元素下标奇偶性相反。

很显然我们需要遍历小O的位置,那么留给我们处理的时间就只有

O

(

log

n

)

O(\log n)

O(logn)了,我们可以利用「前缀和」的思想,预处理出四个数组:

left_odd[i] 代表的是 [1, i] 区间,所有下标为奇数的元素和。left_even[i] 代表的是 [1, i] 区间,所有下标为偶数的元素和。right_odd[i] 代表的是 [i, n] 区间,所有下标为奇数的元素和。right_even[i] 代表的是 [i, n] 区间,所有下标为偶数的元素和。

在遍历小O的位置

i

i

i 时,Alice的糖果数量为 left_odd[i]+right_even[i],Bob的糖果数量为 left_even[i]+right_odd[i]

#include <bits/stdc++.h>

using namespace std;

using i64 = long long;

void find_min(int n, vector<i64>& a) {

if (n == 1) {

cout << 0 << endl;

return;

}

if (n == 2) {

cout << min({ a[0], a[1]}) << endl;

return;

}

vector<i64> left_odd(n + 2);

vector<i64> left_even(n + 2);

vector<i64> right_odd(n + 2);

vector<i64> right_even(n + 2);

for (int i = 1; i <= n; i++) {

left_odd[i] = left_odd[i - 1];

left_even[i] = left_even[i - 1];

if (i % 2) left_odd[i] += a[i];

else left_even[i] += a[i];

}

for (int i = n; i; i--) {

right_odd[i] = right_odd[i + 1];

right_even[i] = right_even[i + 1];

if (i % 2) right_odd[i] += a[i];

else right_even[i] += a[i];

}

i64 min_diff = LLONG_MAX;

for (int i = 1; i <= n; i++) {

i64 a = left_odd[i] + right_even[i];

i64 b = left_even[i] + right_odd[i];

min_diff = min(min_diff, abs(a - b));

}

cout << min_diff << endl;

}

int main() {

int n;

cin >> n;

vector<i64> a(n + 1);

for (int i = 1; i <= n; i++) {

cin >> a[i];

}

find_min(n, a);

return 0;

}

3. 第三题

小O有一个数字串,小O希望把这个数字串分割成两个不含前导零的数字串,使得前半部分可以被

x

x

x 整除,后半部分可以被

y

y

y 整除。请你帮助小O找到一种分割方法。

输入描述

第一行输入一个长度不小于

2

2

2、不超过

1

0

5

10^5

105,且仅由数字字符构成的字符串

s

s

s。

第二行输入两个整数

x

x

x 和

y

(

1

x

,

y

1

0

5

)

y\,(1\leq x,y\leq 10^5)

y(1≤x,y≤105) 代表题中所述的除数。

输出描述

在一行上输出两个数字串

t

1

t_1

t1​ 和

t

2

t_2

t2​,第一个数字串表示分割出的前半部分,第二个数字串表示分割出的后半部分,且满足

s

=

t

1

+

t

2

s=t_1+t_2

s=t1​+t2​。

如果不存在这样的分割方法,直接输出

1

-1

−1。

如果有多种合法答案,您可以输出任意一种。

题解

假设下标从

1

1

1 开始。

和第二题一样,同样是遍历分割的位置,我们同样要在

O

(

log

n

)

O(\log n)

O(logn) 的时间内完成计算。如果使用py的切片计算,必然会超时。我们可以使用第二题的思想,即开一个前后缀数组。prefix[i] 代表的是 s[1..i] 构成的数字除以

x

x

x 的余数,suffix[i] 代表的是 s[i...n] 构成的数字除以

y

y

y 的余数。因此位置

k

k

k 是合理的分割当且仅当 prefix[k]==0suffix[k+1]==0

#include <bits/stdc++.h>

using namespace std;

void solve(string& s, int x, int y) {

int n = s.length();

s = " " + s;

vector<int> prefix(n + 2);

vector<int> suffix(n + 2);

int cur = 0;

for (int i = 1; i <= n; i++) {

cur = (cur * 10 + (s[i] - '0')) % x;

prefix[i] = cur;

}

cur = 0;

int multi = 1;

for (int i = n; i; i--) {

cur = (cur + (s[i] - '0') * multi) % y;

suffix[i] = cur;

multi = (multi * 10) % y;

}

for (int i = 1; i < n; i++) {

if (prefix[i] == 0 && suffix[i + 1] == 0) {

cout << s.substr(1, i) << ' ' << s.substr(i + 1) << endl;

return;

}

}

cout << -1 << endl;

}

int main() {

string s;

cin >> s;

int x, y;

cin >> x >> y;

solve(s, x, y);

return 0;

}



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。