[Luogu 2386]放苹果

Description

题库连接c++

\(n\) 个一样的苹果放在 \(m\) 个一样的盘子里,容许有的盘子空着不放,问共有多少种不一样的分发。多测,数据组数 \(t\)spa

\(1\leq m,n\leq 10, 1\leq t\leq 20\)code

Solution

康复训练 \(\times 3\)ip

下午给学弟讲课时发现了这样一道题...数据彻底能够出到 \(O(n^2)\)固然原题的意思是要用搜索作...get

咱们记 \(f_{i,j}\)\(i\) 个苹果放在 \(j\) 个盘子中的方案数。显然边界条件为 \(\forall i,f_{0,i}=1\),理由是没有苹果时局面只有一种,即任何盘子都为空。it

要注意到这样一个性质,因为盘子均相同,因此 \(f_{i,j}=f_{i,i},j>i\)io

对于 \(\text{DP}\) 方程,考虑第 \(j\) 个盘子怎么放。class

  1. 若第 \(j\) 个盘子不放苹果,那么只需考虑 \(i\) 个苹果放在 \(j-1\) 个盘子中的方案数,即 \(f_{i,j-1}\)
  2. 若第 \(j\) 个盘子放苹果,由常规套路 \(\text{DP}\) 时由无序变有序,盘子放苹果数单调递减。那么若是最后一个盘子都有苹果,则全部盘子都有苹果。咱们将每一个盘子中的苹果数均 \(-1\),就变成了通常状况。此时方案数为 \(f_{i-j,j}\)

综上方程为 \(f_{i,j}=f_{i,j-1}+f_{i-j,j}\)搜索

Code

#include <bits/stdc++.h>
using namespace std;
const int N = 50;

int f[N][N], n, m, t;

int main() {
    for (int i = 0; i < 50; i++) f[0][i] = 1;
    for (int i = 1; i < 50; i++)
        for (int j = 1; j < 50; j++) {
            if (j > i) f[i][j] = f[i][i];
            else f[i][j] = f[i][j-1]+f[i-j][j];
        }
    scanf("%d", &t);
    while (t--) {
        scanf("%d%d", &m, &n);
        printf("%d\n", f[m][n]);
    }
    return 0;   
}
相关文章
相关标签/搜索