【科大讯飞笔试题汇总】2024-07-27-科大讯飞秋招提前批(研发岗)-三语言题解(Cpp/Java/Python)

🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员

✨ 本系列打算持续跟新 秋招笔试题
👏 感谢大家的订阅➕ 和 喜欢💗

📧 清隆这边最近正在收集近一年半互联网笔试题汇总,有需要的小伙伴可以关注 文末 公主号领取~

💡 本次的笔试难度跨度较大,前两题比较简单,最后一题需要 前缀和优化DP 解决,其中 PythonJava 在笔试中据说会超时

在这里插入图片描述

😒 01.心情管理大师

问题描述

K小姐是一名心理咨询师,她最近在研究人们的心情变化规律。她发现,当一个人连续工作时,每天的心情指数会下降 A A A 点;而当这个人休息一天时,心情指数会上升1点。

K小姐想要帮助她的客户A先生进行心情管理。A先生目前的心情指数为0,他计划先连续工作 B B B 天,然后开始休假。K小姐想知道,从A先生开始工作到他的心情指数再次回到0,总共需要多少天。

请你帮助K小姐编写一个程序,计算出这个天数。

输入格式

第一行给出测试用例的数量 T T T

随后 T T T 行,每行给出 A A A B B B 的值,用空格分隔。

输出格式

输出 T T T 行,每行一个整数,表示对应测试用例的答案。

样例输入

2
2 3
3 1

样例输出

9
4

数据范围

1 ≤ T ≤ 100 1 \leq T \leq 100 1T100
1 ≤ A , B ≤ 1000 1 \leq A, B \leq 1000 1A,B1000

题解

  1. 计算 B B B 天工作后的心情指数变化: − A × B -A \times B A×B

  2. 计算需要多少天休息才能让心情指数回到0: A × B A \times B A×B

  3. 3总天数就是工作天数加上休息天数: B + ( A × B ) = B × ( A + 1 ) B + (A \times B) = B \times (A + 1) B+(A×B)=B×(A+1)

因此,我们可以直接用公式 B × ( A + 1 ) B \times (A + 1) B×(A+1) 计算出结果。

参考代码

  • Python
def solve():
    # 读取输入的 a 和 b 值
    a, b = map(int, input().split())
    # 计算并输出结果
    print(b * (a + 1))

# 读取测试用例数量
t = int(input())
# 循环处理每个测试用例
for _ in range(t):
    solve()
  • Java
import java.util.Scanner;

public class Main {
    public static void solve(Scanner sc) {
        // 读取输入的 a 和 b 值
        int a = sc.nextInt();
        int b = sc.nextInt();
        // 计算并输出结果
        System.out.println(b * (a + 1));
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        // 读取测试用例数量
        int t = sc.nextInt();
        // 循环处理每个测试用例
        while (t-- > 0) {
            solve(sc);
        }
        sc.close();
    }
}
  • Cpp
#include <iostream>
using namespace std;

void solve() {
    int a, b;
    // 读取输入的 a 和 b 值
    cin >> a >> b;
    // 计算并输出结果
    cout << b * (a + 1) << endl;
}

int main() {
    int t;
    // 读取测试用例数量
    cin >> t;
    // 循环处理每个测试用例
    while (t--) {
        solve();
    }
    return 0;
}

📝 02.密码学家的挑战

问题描述

K小姐是一位密码学家,她最近在研究一种特殊的加密方法。这种方法将一个十进制数转换为不同进制(2 到 36 进制)的表示,其中 A 表示 10,B 表示 11,以此类推,Z 表示 35。

K小姐发现,某些数字在特定进制下的表示中只包含一个数字 1。她想知道,对于给定的十进制数 n n n,在所有 2 到 36 进制的表示中,最多可以包含多少个数字 1。

请你帮助 K小姐编写一个程序,计算出这个最大值。

输入格式

输入一行,包含一个整数 n n n 1 ≤ n ≤ 3 ⋅ 1 0 5 1 \leq n \leq 3 \cdot 10^5 1n3105),表示给定的十进制数。

输出格式

输出一行,包含一个整数,表示在 2 到 36 进制的所有表示中,数字 1 出现次数的最大值。

样例输入

4

样例输出

2

样例说明

n = 4 n=4 n=4 时,在 3 进制下表示为 ( 11 ) 3 (11)_3 (11)3,包含两个 1,这是最多的情况。

数据范围

1 ≤ n ≤ 3 ⋅ 1 0 5 1 \leq n \leq 3 \cdot 10^5 1n3105

题解

  1. 对于给定的十进制数 n n n,遍历 2 到 36 的所有进制。

  2. 对于每种进制,将 n n n 转换为该进制的表示,并统计其中 1 的个数。

  3. 记录所有进制中 1 的个数的最大值。

关键在于如何高效地进行进制转换和计数。可以使用除法和取模运算来实现进制转换,同时统计 1 的出现次数。

时间复杂度分析:对于每个数 n n n,需要尝试 35 种进制(2 到 36),每次转换的时间复杂度为 O ( log ⁡ n ) O(\log n) O(logn)。因此总的时间复杂度为 O ( 35 log ⁡ n ) O(35 \log n) O(35logn)

参考代码

  • Python
def solve():
    # 读取输入的十进制数
    n = int(input())
    # 初始化最大1的个数为0
    max_ones = 0
    
    # 遍历2到36的所有进制
    for base in range(2, 37):
        num, ones = n, 0
        # 进行进制转换,同时统计1的个数
        while num:
            if num % base == 1:
                ones += 1
            num //= base
        # 更新最大1的个数
        max_ones = max(max_ones, ones)
    
    # 输出结果
    print(max_ones)

# 调用主函数
solve()
  • Java
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        // 读取输入的十进制数
        int n = sc.nextInt();
        // 初始化最大1的个数为0
        int maxOnes = 0;
        
        // 遍历2到36的所有进制
        for (int base = 2; base <= 36; base++) {
            int num = n, ones = 0;
            // 进行进制转换,同时统计1的个数
            while (num > 0) {
                if (num % base == 1) {
                    ones++;
                }
                num /= base;
            }
            // 更新最大1的个数
            maxOnes = Math.max(maxOnes, ones);
        }
        
        // 输出结果
        System.out.println(maxOnes);
        sc.close();
    }
}
  • Cpp
#include <iostream>
#include <algorithm>
using namespace std;

int main() {
    int n;
    // 读取输入的十进制数
    cin >> n;
    // 初始化最大1的个数为0
    int maxOnes = 0;
    
    // 遍历2到36的所有进制
    for (int base = 2; base <= 36; base++) {
        int num = n, ones = 0;
        // 进行进制转换,同时统计1的个数
        while (num) {
            if (num % base == 1) {
                ones++;
            }
            num /= base;
        }
        // 更新最大1的个数
        maxOnes = max(maxOnes, ones);
    }
    
    // 输出结果
    cout << maxOnes << endl;
    return 0;
}

🍿 03.魔法师的序列挑战

问题描述

K小姐是一位魔法师,她最近在研究一种特殊的魔法序列。这种序列具有以下特性:

  • 序列长度为 n n n,每个元素不超过 m m m
  • 序列是非递减的。
  • 序列中所有元素的魔法异或值恰好等于 m m m

K小姐想知道有多少种不同的魔法序列满足这些条件。你能帮助她解决这个难题吗?

输入格式

输入一行,包含两个整数 n n n m m m 1 ≤ n ≤ 300 1 \leq n \leq 300 1n300 0 ≤ m ≤ 300 0 \leq m \leq 300 0m300),分别表示序列的长度和魔法异或值。

输出格式

输出一个整数,表示满足条件的魔法序列的数量。由于答案可能很大,请对 1 0 9 + 7 10^9 + 7 109+7 取模后输出。

样例输入1

3 2

样例输出1

4

样例输入2

200 200

样例输出2

391022064

数据范围

  • 1 ≤ n ≤ 300 1 \leq n \leq 300 1n300
  • 0 ≤ m ≤ 300 0 \leq m \leq 300 0m300

题解

这个问题可以使用动态规划来解决。定义状态 d p [ i ] [ j ] [ k ] dp[i][j][k] dp[i][j][k] 表示长度为 i i i,最后一个数是 j j j,异或和为 k k k 的方案数。

状态转移方程为:

d p [ i ] [ j ] [ k ] = ∑ 0 ≤ l ≤ j d p [ i − 1 ] [ l ] [ k ⊕ j ] dp[i][j][k] = \sum_{0 \leq l \leq j} dp[i-1][l][k \oplus j] dp[i][j][k]=0ljdp[i1][l][kj]

其中 ⊕ \oplus 表示异或操作。

为了优化时间复杂度,可以使用前缀和来加速计算。最终的时间复杂度为 O ( n ⋅ m 2 ) O(n \cdot m^2) O(nm2)

据考友反馈,在笔试的时候pythonjava 代码是会超时的,建议冲 cpp

参考代码

  • Python
MOD = 10**9 + 7

def solve():
    n, m = map(int, input().split())
    
    # 初始化DP数组
    dp = [[[0] * (2*m+1) for _ in range(m+1)] for _ in range(n+1)]
    
    # 初始化长度为1的情况
    for j in range(m+1):
        dp[1][j][j] = 1
    
    # 动态规划过程
    for i in range(2, n+1):
        # 计算前缀和
        prefix_sum = [[0] * (2*m+1) for _ in range(m+1)]
        for j in range(m+1):
            for k in range(2*m+1):
                prefix_sum[j][k] = dp[i-1][j][k]
                if j > 0:
                    prefix_sum[j][k] = (prefix_sum[j][k] + prefix_sum[j-1][k]) % MOD
        
        # 状态转移
        for j in range(m+1):
            for k in range(2*m+1):
                if k ^ j <= 2*m:
                    dp[i][j][k] = prefix_sum[j][k ^ j]
    
    # 计算最终结果
    ans = sum(dp[n][j][m] for j in range(m+1)) % MOD
    print(ans)

solve()
  • Java
import java.util.Scanner;

public class Main {
    static final int MOD = 1000000007;
    static final int N = 301;
    static int[][][] dp = new int[N][N][N << 1];
    static int[][] prefixSum = new int[N][N << 1];

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();

        // 初始化长度为1的情况
        for (int j = 0; j <= m; j++) {
            dp[1][j][j] = 1;
        }

        // 动态规划过程
        for (int i = 2; i <= n; i++) {
            // 计算前缀和
            for (int j = 0; j <= m; j++) {
                for (int k = 0; k <= m * 2; k++) {
                    prefixSum[j][k] = dp[i - 1][j][k];
                    if (j > 0) {
                        prefixSum[j][k] = (prefixSum[j][k] + prefixSum[j - 1][k]) % MOD;
                    }
                }
            }

            // 状态转移
            for (int j = 0; j <= m; j++) {
                for (int k = 0; k <= 2 * m && (k ^ j) <= 2 * m; k++) {
                    dp[i][j][k] = prefixSum[j][k ^ j];
                }
            }
        }

        // 计算最终结果
        int ans = 0;
        for (int j = 0; j <= m; j++) {
            ans = (ans + dp[n][j][m]) % MOD;
        }

        System.out.println(ans);
    }
}
  • Cpp
#include <iostream>
#include <vector>
using namespace std;

const int MOD = 1e9 + 7;
const int N = 301;

int dp[N][N][N << 1];  // DP数组,dp[i][j][k]表示长度为i,最后一个数是j,异或和为k的方案数
int prefix_sum[N][N << 1];  // 前缀和数组,用于优化计算

int main() {
    int n, m;
    cin >> n >> m;

    // 初始化长度为1的情况
    for (int j = 0; j <= m; ++j) {
        dp[1][j][j] = 1;
    }

    // 动态规划过程
    for (int i = 2; i <= n; i++) {
        // 计算前缀和
        for (int j = 0; j <= m; j++) {
            for (int k = 0; k <= m * 2; k++) {
                prefix_sum[j][k] = dp[i - 1][j][k];
                if (j > 0) {
                    prefix_sum[j][k] = (prefix_sum[j][k] + prefix_sum[j - 1][k]) % MOD;
                }
            }
        }

        // 状态转移
        for (int j = 0; j <= m; j++) {
            for (int k = 0; k <= 2 * m && (k ^ j) <= 2 * m; k++) {
                dp[i][j][k] = prefix_sum[j][k ^ j];
            }
        }
    }

    // 计算最终结果
    int ans = 0;
    for (int j = 0; j <= m; ++j) {
        ans = (ans + dp[n][j][m]) % MOD;
    }

    cout << ans << "\n";

    return 0;
}
  • 36
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清隆Coding

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值