计算总和可被 k 整除的子序列总数
Count total subsequences whose sum is divisible by k
我正在尝试为问题编写一个 DP 解决方案:计算一个数组的元素总和可被 k 整除的子序列总数。
我写了下面的解决方案。但它没有给出正确的结果。如下面的代码片段,数组为{1, 2, 1},k = 3。所以期望被3整除的子序列总数是2,但实际结果是3,这显然是不正确的。
请指出我的错误
private int countDP(int[] a, int k)
{
int L = a.length;
int[][] DP = new int[L][k];
for(int i = 0; i < DP.length; i++)
{
for(int j = 0; j < DP[0].length; j++)
DP[i][j] = -1;
}
int res = _countDP(a, k, DP, 0, 0);
return res;
}
private int _countDP(int[] a, int k, int[][] DP, int idx, int m) //Not giving the correct result.
{
if(idx == a.length)
return m == 0 ? 1 : 0;
if(DP[idx][m] != -1)
return DP[idx][m];
int ans = 0;
ans = _countDP(a, k, DP, idx + 1, m);
ans += _countDP(a, k, DP, idx + 1, (m + a[idx]) % k);
return DP[idx][m] = ans;
}
public static void main(String[] args)
{
CountSubnsequences cs = new CountSubnsequences();
int[] a = {1, 2, 1};
int k = 3;
int total1 = cs.countDP(a, k);
System.out.println("Total numeber of sub sequences: " + total1);
}
设 s
表示长度为 N
的序列,K
为给定的除数。
dp[i][j]
= s[0..i]
余数等于 j
的子序列数。我们将为所有 0 <= i < N
和 0 <= j < K
.
计算 dp
dp[i][j] = 0 for all (i, j)
dp[0][0] += 1
dp[0][s[0] mod K] += 1
for i = 1 .. N - 1
for j = 0 .. K - 1
dp[i][j] = dp[i - 1][j]
for j = 0 .. K - 1
dp[i][(j + s[i]) mod K] += dp[i - 1][j]
结果是dp[N - 1][0]
int fun(int i,int s)
{
if(i==1){
if(s-a[i]!=0 && (s-a[i])%k==0)
return 1;
else
return 0;}
else{
if((s-a[i])%k==0){
return 1+fun(i-1,s-a[i])+fun(i-1,s);
}
else{
return fun(i-1,s-a[i])+fun(i-1,s);
}
}
}
Python @piotrekg2 解决方案的代码。
看起来不错!
from typing import List
# dp[i][j] = the number of subsequences of length i with remainder equal to j.
def count_subseq(s: List[int],k):
n = len(s)
dp = [0]*k
dp[0] = 1 # i=0, remainder=0, only 1 subseq
for i in range(1,n+1):
dp2 = dp.copy() # copy previous i-length results: results without s[i] in subseq
for j in range(k):
dp2[(j+s[i-1])%k] += dp[j]
dp = dp2
return dp[0]
if __name__ == '__main__':
print(count_subseq([2,3,5,8],5))
print(count_subseq([5,5,5],5))
遇到了同样的问题。但最终得到了答案。
返回的答案总是比所有可能的子序列多1。这是因为我们知道 0 始终是有效答案。因此,如果假设您不从数组中选择任何单个元素,则总和 = 0。因此,它将其视为有效答案并将我们的答案递增 1。因此,要获得实际答案,只需将返回值递减 1。
我正在尝试为问题编写一个 DP 解决方案:计算一个数组的元素总和可被 k 整除的子序列总数。
我写了下面的解决方案。但它没有给出正确的结果。如下面的代码片段,数组为{1, 2, 1},k = 3。所以期望被3整除的子序列总数是2,但实际结果是3,这显然是不正确的。
请指出我的错误
private int countDP(int[] a, int k)
{
int L = a.length;
int[][] DP = new int[L][k];
for(int i = 0; i < DP.length; i++)
{
for(int j = 0; j < DP[0].length; j++)
DP[i][j] = -1;
}
int res = _countDP(a, k, DP, 0, 0);
return res;
}
private int _countDP(int[] a, int k, int[][] DP, int idx, int m) //Not giving the correct result.
{
if(idx == a.length)
return m == 0 ? 1 : 0;
if(DP[idx][m] != -1)
return DP[idx][m];
int ans = 0;
ans = _countDP(a, k, DP, idx + 1, m);
ans += _countDP(a, k, DP, idx + 1, (m + a[idx]) % k);
return DP[idx][m] = ans;
}
public static void main(String[] args)
{
CountSubnsequences cs = new CountSubnsequences();
int[] a = {1, 2, 1};
int k = 3;
int total1 = cs.countDP(a, k);
System.out.println("Total numeber of sub sequences: " + total1);
}
设 s
表示长度为 N
的序列,K
为给定的除数。
dp[i][j]
= s[0..i]
余数等于 j
的子序列数。我们将为所有 0 <= i < N
和 0 <= j < K
.
dp
dp[i][j] = 0 for all (i, j)
dp[0][0] += 1
dp[0][s[0] mod K] += 1
for i = 1 .. N - 1
for j = 0 .. K - 1
dp[i][j] = dp[i - 1][j]
for j = 0 .. K - 1
dp[i][(j + s[i]) mod K] += dp[i - 1][j]
结果是dp[N - 1][0]
int fun(int i,int s)
{
if(i==1){
if(s-a[i]!=0 && (s-a[i])%k==0)
return 1;
else
return 0;}
else{
if((s-a[i])%k==0){
return 1+fun(i-1,s-a[i])+fun(i-1,s);
}
else{
return fun(i-1,s-a[i])+fun(i-1,s);
}
}
}
Python @piotrekg2 解决方案的代码。 看起来不错!
from typing import List
# dp[i][j] = the number of subsequences of length i with remainder equal to j.
def count_subseq(s: List[int],k):
n = len(s)
dp = [0]*k
dp[0] = 1 # i=0, remainder=0, only 1 subseq
for i in range(1,n+1):
dp2 = dp.copy() # copy previous i-length results: results without s[i] in subseq
for j in range(k):
dp2[(j+s[i-1])%k] += dp[j]
dp = dp2
return dp[0]
if __name__ == '__main__':
print(count_subseq([2,3,5,8],5))
print(count_subseq([5,5,5],5))
遇到了同样的问题。但最终得到了答案。
返回的答案总是比所有可能的子序列多1。这是因为我们知道 0 始终是有效答案。因此,如果假设您不从数组中选择任何单个元素,则总和 = 0。因此,它将其视为有效答案并将我们的答案递增 1。因此,要获得实际答案,只需将返回值递减 1。