首页 > 试题广场 >

模意义下最大子序列和(Easy Version)

[编程题]模意义下最大子序列和(Easy Version)
  • 热度指数:1649 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
\hspace{15pt}给定一个含有 n 个正整数的数组 a 以及一个正整数模数 m。你可以任选若干下标递增的元素构成一个子序列(允许选择空序列)。设所选元素之和为 S,求 S \bmod m最大可能值

输入描述:
\hspace{15pt}第一行输入两个整数 n,m\ (1\leqq n\leqq 15,\;1\leqq m\leqq 10^9)
\hspace{15pt}第二行输入 n 个整数 a_i\ (1\leqq a_i\leqq 10^9)


输出描述:
\hspace{15pt}输出一个整数,表示 S \bmod m 的最大值。
示例1

输入

1 1
1

输出

0

说明

可选子序列有 \varnothing(空序列)和 (1),其元素和分别为 01;取模 m=1 后结果均为 0,因此答案为 0
#include <iostream>
#include <vector>
using namespace std;
using ll = long long;

int n;
ll m, ans = 0;
vector<ll> a;

// dfs(i, sum) 表示当前在处理下标 i,已经累加的模值为 sum
void dfs(int i, ll sum) {
    if (i == n) {
        ans = max(ans, sum);  // sum 本身就是 mod m 后的值
        return;
    }
    // 不选 a[i]
    dfs(i + 1, sum);
    // 选 a[i]
    dfs(i + 1, (sum + a[i] % m) % m);
}

int main() {

    cin >> n >> m;
    a.resize(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
        a[i] %= m;
    }

    dfs(0, 0);
    cout << ans << "\n";
    return 0;
}
发表于 2025-07-25 09:50:07 回复(0)
import java.util.*;

public class Main {
    static int res = 0;
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int m = in.nextInt();
        int[] arr = new int[n];
        for (int i = 0; i < n; i++) {
            arr[i] = in.nextInt();
            arr[i] %= m; // 预处理,减少后续计算量
        }
        track(arr, 0, n, m, 0);
        System.out.println(res);
    }
   
    // public static void track(int[] arr, int index, int n, int m, int sum) {
    //     if (index == n) {
    //         res = Math.max(res, sum);
    //         return;
    //     }
    //     // 选择当前元素
    //     track(arr, index + 1, n, m, (sum + arr[index]) % m);
    //     // 不选择当前元素
    //     track(arr, index + 1, n, m, sum);
    // }

    public static void track(int[] arr, int index, int n, int m, int sum) {
        // 每次递归都尝试更新最大值
        res = Math.max(res, sum);

        // 从当前index开始,尝试所有可能的子序列
        for (int i = index; i < n; i++) {
            // 选择arr[i],并递归处理后面的元素
            track(arr, i + 1, n, m, (sum + arr[i]) % m);
        }
    }
}

发表于 2025-09-22 21:42:00 回复(0)
package main

import (
	"fmt"
)

func main() {
	var n, m int
	fmt.Scanf("%d %d", &n, &m)
	k := make([]int, n)
	for i := 0; i < n; i++ {
		fmt.Scanf("%d", &k[i])
	}

	result := 0

	var dfs func(i, sum int)
	dfs = func(i, sum int) {
		if i == n {
			modSum := sum % m
			if modSum > result {
				result = modSum
			}
			return
		}
		// 不选择当前元素
		dfs(i+1, sum)
		// 选择当前元素
		dfs(i+1, sum+k[i])
	}

	dfs(0, 0)
	fmt.Println(result)
}

发表于 2025-09-07 22:40:57 回复(0)
# 更新答案(考虑当前子序列)
  
n, m = map(int, input().strip().split())
a = list(map(int, input().strip().split()))
ans = 0

def dfs(i, current_sum):
    global ans
    # 更新答案(考虑当前子序列)
    ans = max(ans, current_sum % m)

    # 递归边界
    if i == n:
        return

    # 选择当前元素
    dfs(i + 1, (current_sum + a[i]) % m)

    # 不选择当前元素
    dfs(i + 1, current_sum)

# 从第一个元素开始,初始和为0
dfs(0, 0)
print(ans)

发表于 2025-08-23 13:19:34 回复(0)