【笔试刷题】OPPO-2026.03.14-改编真题

✅ 春招备战指南 ✅

💡 学习建议:

  • 先尝试独立解题
  • 对照解析查漏补缺

🧸 题面描述背景等均已深度改编,做法和题目本质基本保持一致。

🍹 感谢各位朋友们的订阅,你们的支持是我们创作的最大动力

🌸 目前本专栏已经上线200+套真题改编解析,后续会持续更新的

春秋招笔试机考招合集 -> 互联网必备刷题宝典🔗

OPPO-2026.03.14

这套题的层次很清楚:第 1 题基本就是按题意模拟并做一次整除判断,属于热身;第 2 题虽然套了斐波那契背景,但真正考的是把带权区间和化成前缀公式;第 3 题的数据范围看起来很大,实际有效状态只和 这些数字有关,关键是先把“选集合”和“排顺序”拆开。

题目一:三号位求和校验

这题没有隐藏技巧,按下标扫描出所有位置是 的倍数的元素,再判断和是否能被 整除即可。最容易犯的错反而是下标从 开始还是从 开始看错。

难度:简单

题目二:斐波那契带权区间和

核心不是暴力求和,而是先推前缀和公式 。有了这个式子以后,每个询问都能转成两个前缀值的差,再配合预处理斐波那契数列就能线性扫完所有询问。

难度:中等

题目三:看看的正整数计数

这题的关键转换是:先选出哪些数字,再考虑这些数字能排成多少个不同的正整数。因为可用数字只有 ,所以预处理一个“和 + 选了几个数”的小 DP 就足够了,真正容易漏的是别把 误算成一种方案。

难度:中等

1. 三号位求和校验

问题描述

小基 正在整理一组整数序列。她只关心那些下标恰好是 的整数倍的位置。

给定一个长度为 的整数数组 ,请计算所有满足下标是 的整数倍的元素之和,并判断这个和是否为 的整数倍。

输入格式

第一行输入一个整数 ,表示数组长度。

第二行输入 个整数 ,表示数组元素。

输出格式

如果所求的和是 的整数倍,输出 Yes;否则输出 No

输出大小写必须与题面一致。

样例输入

6
1 2 3 4 5 6

样例输出

Yes
样例 解释说明
样例1 下标为 的整数倍的位置是 ,对应元素和为 ,它是 的整数倍,所以输出 Yes

数据范围

题解

这题完全按题意模拟即可。

因为数组下标从 开始,所以我们只需要枚举所有位置,挑出满足:

的那些下标,把对应元素累加起来,最后判断总和是否满足:

即可。

这里唯一需要小心的是下标起点。题目里写的是 ,所以位置编号从 开始,不是从 开始。

复杂度分析

只需要扫描一遍数组。

  • 时间复杂度:
  • 空间复杂度:

参考代码

  • Python
import sys

input = lambda: sys.stdin.readline().strip()


def solve() -> None:
    n = int(input())
    arr = list(map(int, input().split()))

    total = 0
    # 题目下标从 1 开始,因此位置 i 对应数组下标 i - 1。
    for i in range(1, n + 1):
        if i % 3 == 0:
            total += arr[i - 1]

    print("Yes" if total % 3 == 0 else "No")


if __name__ == "__main__":
    solve()
  • Cpp
#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n;
    cin >> n;
    long long total = 0;
    for (int i = 1; i <= n; ++i) {
        int x;
        cin >> x;
        // 位置编号从 1 开始,只统计 3 的倍数位置。
        if (i % 3 == 0) {
            total += x;
        }
    }

    cout << (total % 3 == 0 ? "Yes" : "No") << '\n';
    return 0;
}
  • Java
import java.io.*;
import java.util.*;

public class Main {
    static class FastScanner {
        private final BufferedInputStream in = new BufferedInputStream(System.in);
        private final byte[] buffer = new byte[1 << 16];
        private int ptr = 0, len = 0;

        private int read() throws IOException {
            if (ptr >= len) {
                len = in.read(buffer);
                ptr = 0;
                if (len <= 0) {
                    return -1;
                }
            }
            return buffer[ptr++];
        }

        int nextInt() throws IOException {
            int c;
            while ((c = read()) <= ' ') {
                if (c == -1) {
                    return -1;
                }
            }
            int sign = 1;
            if (c == '-') {
                sign = -1;
                c = read();
            }
            int val = 0;
            while (c > ' ') {
                val = val * 10 + (c - '0');
                c = read();
            }
            return val * sign;
        }
    }

    public static void main(String[] args) throws Exception {
        FastScanner fs = new FastScanner();
        int n = fs.nextInt();
        long total = 0;

        for (int i = 1; i <= n; i++) {
            int x = fs.nextInt();
            // 题目下标从 1 开始。
            if (i % 3 == 0) {
                total += x;
            }
        }

        System.out.println(total % 3 == 0 ? "Yes" : "No");
    }
}

2. 斐波那契带权区间和

问题描述

小毛在复盘一组经典递推时,定义斐波那契数列 为:

  • 时,
  • 时,

接着他又定义:

以及区间和:

现在有 次询问。每次给出两个整数 ,请你计算:

输入格式

第一行输入一个整数 ,表示询问次数。

接下来 行,每行输入两个整数 ,表示一组询问。

输出格式

输出 行,每行输出对应询问的答案。

样例输入

1
1 3

样例输出

9
样例 解释说明
样例1 ,因此 ,区间和为

数据范围

题解

如果对每个询问都直接把区间扫一遍,显然会超时。关键在于先把前缀和公式推出来。

设:

这道题有一个常用恒等式:

因此区间答案就变成:

也就是:

接下来问题就只剩一件事:快速得到所有会用到的斐波那契值。

由于题目中的 最大只有 ,直接把斐波那契数列预处理到 就够了。这样每个询问只需要代一次公式,时间就是

为什么公式是对的

这里给一个常见的结论性写法。把:

做整理后,可以验证它满足:

而右边的闭式:

同样满足:

并且 ,所以两者恒等。

复杂度分析

设所有询问里最大的右端点是

  • 预处理斐波那契数列的复杂度:
  • 每次询问计算答案的复杂度:
  • 总复杂度:
  • 空间复杂度:

参考代码

  • Python
import sys

input = lambda: sys.stdin.readline().strip()
MOD = 10**9 + 7


def prefix(n: int, fib: list[int]) -> int:
    if n <= 0:
        return 0
    # S(n) = n * F(n + 2) - F(n + 3) + 2
    return (n * fib[n + 2] - fib[n + 3] + 2) % MOD


def solve() -> None:
    q = int(input())
    queries = []
    max_r = 0
    for _ in range(q):
        l, r = map(int, input().split())
        queries.append((l, r))
        max_r = max(max_r, r)

    # 需要用到 F(r + 3),因此开到 max_r + 3。
    fib = [0] * (max_r + 4)
    fib[1] = fib[2] = 1
    for i in range(3, max_r + 4):
        fib[i] = (fib[i - 1] + fib[i - 2]) % MOD

    out = []
    for l, r in queries:
        ans = (prefix(r, fib) - prefix(l - 1, fib)) % MOD
        out.append(str(ans))
    sys.stdout.write("\n".join(out))


if __name__ == "__main__":
    solve()
  • Cpp
#include <bits/stdc++.h>
using namespace std;

static const long long MOD = 1000000007LL;

long long prefixSum(int n, const vector<long long>& fib) {
    if (n <= 0) {
        return 0;
    }
    // S(n) = n * F(n + 2) - F(n + 3) + 2
    return (1LL * n * fib[n + 2] - fib[n + 3] + 2 + MOD) % MOD;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int q;
    cin >> q;
    vector<pair<int, int>> queries(q);
    int maxR = 0;
    for (int i = 0; i < q; ++i) {
        int l, r;
        cin >> l >> r;
        queries[i] = {l, r};
        maxR = max(maxR, r);
    }

    vector<long long> fib(maxR + 4, 0);
    fib[1] = fib[2] = 1;
    for (int i = 3; i <= maxR + 3; ++i) {
        fib[i] = (fib[i - 1] 

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

互联网刷题笔试宝典 文章被收录于专栏

互联网刷题笔试宝典,这里涵盖了市面上大部分的笔试题合集,希望助大家春秋招一臂之力

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务