I want to count the number of combinations we can prouduce of a given number.
例如M =数字位数,N = 4数字长度
M= 3 ({3,7,5}) and N=4
Possible combinations:(The given 3 numbers must be there in the combination)
3577, 3557, 7353 and 5735 and other (32 possible combination)
我在网上找到了这个代码。这段代码给了我正确的输出,但我无法理解它正在使用什么逻辑。
请解释下面的代码及其时间复杂程度。
提前致谢。
#define LL long long int
#define sd(x) scanf("%d", &x)
#define MOD 1000000007
#define D double
#define LD long double
#define N 200
LL dp[N][N];
inline void solve(){
int n, m, i, j;
sd(m); sd(n);
memset(dp, 0, sizeof dp);
dp[1][1] = m;
for(i = 1; i < n; i++){
for(j = 1; j <= i && j <= m; j++){
(dp[i + 1][j] += j * dp[i][j]) %= MOD;
(dp[i + 1][j + 1] += (m - j) * dp[i][j]) %= MOD;
}
}
cout<<dp[n][m]<<endl;
}
答案 0 :(得分:1)
代码中的dp
代表dynamic programming
。在许多编程竞赛平台中,它都是state
。
问题出在此处:
dp[i][j]
表示在j
中使用M
个不同数字形成长度为i
的数字的方式。一些要求:j <= i
和j <= M
。
所以我们假设,我们已经知道dp[i][j]
。
然后我们可以简单地计算dp[i + 1][j] = j * dp[i][j]
(再多一个插槽)。
对于dp[i + 1][j + 1]
,这意味着我们可以在插槽中插入一个插槽和 M-j 选项。所以dp[i + 1][j + 1] = (M - j) * dp[i][j]
。
为什么M - j
?回想一下
j
中的
M
不同的数字
最后,通过这两个转换公式和dp[1][1]
,我们可以计算dp[i][j]
和i <= N
中的任何j <= M and j <= i
。
更新:示例
N = 4
,M = 3
。
我们首先计算dp[1][1]
,显然是dp[1][1] = 3
。只有一个广告位,我们有M
个选项。 (回忆dp
)的定义
然后我们进入循环:从dp[1][1]
开始:
计算dp[1 + 1][1]
:这意味着我们有两个插槽和一个数字。我们这里只有一个选择 - 再次使用相同的数字。所以dp[1 + 1][1] = 1 * dp[1][1] = 3
。在您的示例中,dp[2][1]
代表{3, 3} {5, 5} {7, 7}
;
要计算dp[1 + 1][1 + 1]
:这意味着我们有两个广告位和两个不同的数字,因此我们有M - 1
个选项。所以它等于dp[2][2] = 2 * dp[1][1] = 6
。在您的示例中,dp[2][2] represents
{3, 5}, {3, 7}, {5, 3}, {5, 7}, {7, 3}, {7, 5}
。
然后按照循环,我们将转到dp[4][3]
,这就是答案。