AI代码陪练第三日

419 阅读2分钟

问题描述

给定一个数组,请你把数组里的数字分为两组,使一组数字和的个位数等于 A(1 ≤ A ≤ 9),且剩余数字和的个位数等于 B(1 ≤ B ≤ 9);或者一组数字的个数为零,但剩余数字和的个位数等于 A 或 B。请问一共有多少种划分方式?

备注:

  1. 数组里的数字可以相等,但每个数字都是独一无二的。 比如数组 a 等于[1, 1, 1],A 等于 1,B 等于 2,则一共有三组划分方式: 第一种: A:a[0] B:a[1]、a[2] 第二种: A:a[1] B:a[0]、a[2] 第三种: A:a[2] B:a[0]、a[1]

  2. 可以将所有数字都划分到同一组,使其和的个位数等于 A 或 B;另一组为空 比如数组 a 等于[1, 1, 1],A 等于 3,B 等于 5,则共有一组划分方式: A:a[0]、a[1]、a[2] B:空

输入格式

输入第一行包含三个整数 n、A、B(1 ≤ n ≤ 100000,1 ≤ A ≤ 9,1 ≤ B ≤ 9),n 代表需要数组中的数字个数。

第二行,有 n 个元素,代表数组内的数字(1 ≤ 每个数字 ≤ 9)。

输出格式

输出一共有多少种划分方式,结果对 10000007 取余。

输入样例

样例 1

3 1 2

1 1 1

样例 2

3 3 5

1 1 1

样例 3

2 1 1

1 1

输出样例

样例 1

3

样例 2

1

样例 3

2

20240918174500.jpg

解题:

function solution(n, A, B, numbers) {
  const MOD = 10000007; // 结果取模的常量  
  let totalSum = numbers.reduce((sum, num) => sum + num, 0); // 计算数组的总和  

  // 创建 dp 数组,记录形成各个位数和的组合数  
  let dp = new Array(10).fill(0); // dp[0] 到 dp[9],共 10 个元素  
  dp[0] = 1; // 形成和为 0 的方式有 1 种:不取任何数字  

  // 遍历数组中的每个数字  
  for (let num of numbers) {
    // 从后向前更新 dp 数组,防止覆盖  
    for (let j = 9; j >= num; j--) {
      dp[j] = (dp[j] + dp[j - num]) % MOD; // 更新组合数  
    }
  }

  // 计算符合条件的组合数  
  let count = 0;

  // 处理一组为空的情况  
  count = (count + dp[A]) % MOD; // 和为 A 的组合数  
  count = (count + dp[B]) % MOD; // 和为 B 的组合数  

  // 处理两组都有数字的情况  
  for (let i = 0; i < 10; i++) {
    if (i === A || i === B) continue; // 跳过 A 和 B  
    let j = (totalSum - i) % 10; // 剩余和的个位数  
    if ((i === A && j === B) || (i === B && j === A)) {
      count = (count + dp[i]) % MOD; // 统计符合条件的组合数  
    }
  }

  return count; // 返回结果  
}


function main() {
  //  You can add more test cases here
  console.log(solution(3, 1, 2, [1, 1, 1]) === 3);
  console.log(solution(3, 3, 5, [1, 1, 1]) === 1);
  console.log(solution(2, 1, 1, [1, 1]) === 2);
}

main();