问题描述
小F面临一个有趣的挑战:给定一个数组,她需要将数组中的数字分为两组。分组的目标是使得一组数字的和的个位数等于给定的 A,另一组数字的和的个位数等于给定的 B。除此之外,还有一种特殊情况允许其中一组为空,但剩余数字和的个位数必须等于 A 或 B。小F需要计算所有可能的划分方式。
例如,对于数组 [1, 1, 1] 和目标 A = 1,B = 2,可行的划分包括三种:每个 1 单独作为一组,其余两个 1 形成另一组。如果 A = 3,B = 5,当所有数字加和的个位数为 3 或 5 时,可以有一组为非空,另一组为空。
测试样例
样例1:
输入:
n = 3,A = 1,B = 2,array_a = [1, 1, 1]
输出:3
样例2:
输入:
n = 3,A = 3,B = 5,array_a = [1, 1, 1]
输出:1
样例3:
输入:
n = 2,A = 1,B = 1,array_a = [1, 1]
输出:2
样例4:
输入:
n = 5,A = 3,B = 7,array_a = [2, 3, 5, 7, 9]
输出:0
解题思路
问题分析
这道题目是一个组合问题,要求我们找出将给定数组分成两组的所有可能方式,使得一组数字和的个位数等于给定的 A,另一组数字和的个位数等于给定的 B。这里有两个关键点:
- 个位数匹配:我们需要确保每组数字和的个位数分别与 A 和 B 相匹配。这意味着我们只关心数字和的个位数,而不是总和本身。
- 特殊情况处理:如果数组中所有数字的总和的个位数等于 A 或 B,那么允许其中一组为空。这增加了问题的复杂性,因为我们需要考虑所有可能的子集,包括空集。
为了解决这个问题,我们可以使用动态规划。我们定义一个二维数组 dp,其中 dp[i][j] 表示前 i 个数字能否分成两组,使得一组数字和的个位数为 j。我们初始化 dp[0][0] 为 true,因为没有任何数字时,和为 0 是可接受的。然后,我们遍历数组,对于每个数字,我们检查将其放入第一组或第二组是否满足条件。最后,我们检查 dp[n][A] 和 dp[n][B] 的值来确定可能的划分方式的数量,并考虑特殊情况,即如果总和的个位数等于 A 或 B,则可以有一组为空。
这个问题的关键在于理解个位数的计算和如何使用动态规划来跟踪所有可能的划分。通过这种方法,我们可以系统地探索所有可能的组合,并计算出满足给定条件的划分方式的数量。
思路:动态规划
统计划分方式存在这几种情况:
方式1:所有个位数为A
方式2:所有的个位数为B
方式3:所有的个位数和为A/B
方式4:拆解成两个数组,A数组和B数组,统计等于A和B的个数
-
初始化动态规划数组:
dp[i][a][b]表示前i个数字分成两组,第一组和个位数为a,第二组和个位数为b的组合数量。初始化dp[0][0][0]=1。(没有任何数字的时候,有一种方式使得和为0)。 -
状态转移
- 如果放到A组
if(dp[i][a][b]>0) dp[i+1][(a+num[i])%10][b]+=dp[i][a][b] - 如果放到B组
if(dp[i][a][b]>0) dp[i+1][a][(b+num[i])%10]+=dp[i][a][b]
- 最终
dp[n][a][b]既包含方式3也包含4 - 最终统计方式1和方式2的情况。
完整代码:
import java.util.Arrays;
public class Main {
public static int solution(int n, int A, int B, int[] array) {
int[][][] dp = new int[n + 1][10][10];
dp[0][0][0] = 1;
for (int i = 0; i < n; i++) {
for (int a = 0; a < 10; a++) {
for (int b = 0; b < 10; b++) {
if (dp[i][a][b] > 0) {
dp[i + 1][(a + array[i]) % 10][b] += dp[i][a][b];
dp[i + 1][a][(b + array[i]) % 10] += dp[i][a][b];
}
}
}
}
int result = dp[n][A][B];
int total=0;
for(int i=0;i<n;i++)
{
total+=array[i];
}
if(total%10==A)
result+=1;
if(total%10==B)
result+=1;
return result;
}
public static void main(String[] args) {
System.out.println(solution(3, 1, 2, new int[] { 1, 1, 1 })); // 输出应为 3
System.out.println(solution(3, 3, 5, new int[] { 1, 1, 1 })); // 输出应为 1
System.out.println(solution(2, 1, 1, new int[] { 1, 1 })); // 输出应为 2
System.out.println(solution(5, 3, 7, new int[] { 2, 3, 5, 7, 9 })); // 输出应为 0
}
}