#include <iostream>
#include <vector>
#include <fstream>
#include <algorithm>
 
using namespace std;
 
// Hằng số giới hạn (N <= 8000)
const int MAXN = 8005;
 
// Mảng tiền xử lý cho Tổ hợp (Combinatorics)
// C[i][j] = tổ hợp chập j của i (i choose j)
long long C[MAXN][MAXN];
 
// Hàm tiền xử lý Tổ hợp (nCk)
// Sử dụng công thức Pascal: C[n][k] = C[n-1][k-1] + C[n-1][k]
void precompute_combinations() {
    // Khởi tạo cơ sở
    for (int i = 0; i < MAXN; ++i) {
        C[i][0] = 1; // C[i][0] = 1
        for (int j = 1; j <= i; ++j) {
            // Đảm bảo không vượt quá giới hạn mảng
            if (i > 0) {
                C[i][j] = C[i-1][j-1] + C[i-1][j];
                // Lưu ý: Nếu đề bài yêu cầu Modulo, cần thực hiện phép % tại đây.
                // Giả sử đề bài không yêu cầu Modulo vì không có đề cập rõ.
            }
        }
    }
}
 
/**
 * @brief Hàm tính số cách chia tổng (N_prime) thành (K_prime) số nguyên dương.
 * @details Tương đương với tổ hợp C(N_prime - 1, K_prime - 1).
 * @param N_prime Tổng cần chia.
 * @param K_prime Số lượng phần tử.
 * @return Số cách chia.
 */
long long combinations(int N_prime, int K_prime) {
    if (K_prime <= 0 || N_prime < K_prime) {
        return 0;
    }
    // Bài toán chia N thành K phần: C(N-1, K-1)
    return C[N_prime - 1][K_prime - 1];
}
 
 
// Hàm giải quyết bài toán cho một k cụ thể
long long solve_for_k(int k, int N, int M) {
    // 1. Tổng số cách chia N thành k số nguyên dương (Không có ràng buộc M)
    // C(N-1, k-1)
    long long result = combinations(N, k);
 
    // 2. Áp dụng Nguyên lý Bao hàm - Loại trừ (Inclusion-Exclusion)
    // Loại bỏ các trường hợp có ít nhất 's' số bị lặp >= M+1 lần.
 
    // s là số lượng giá trị (ví dụ: x1, x2, ...) vi phạm điều kiện M (lặp >= M+1 lần)
    for (int s = 1; ; ++s) {
        // Tổng giá trị nhỏ nhất đã bị sử dụng bởi s số vi phạm: s * (M + 1) * 1 (nếu tất cả vi phạm đều là số 1)
        int min_val_used = s * (M + 1);
        if (min_val_used > N) {
            break; // Không thể vi phạm quá s số
        }
 
        // s_sum là tổng giá trị tối thiểu đã bị sử dụng bởi s số vi phạm.
        // Tuy nhiên, do các số vi phạm x1, x2, ... có thể khác nhau, ta không thể tính trực tiếp.
        // Ta chỉ có thể tính tổng số cách chọn s vị trí vi phạm (chọn s số x1, x2,...)
 
        // Cách đơn giản hóa cho bài toán này (do tính đối xứng):
        // Giả sử tất cả s số vi phạm đều là số 1 (x1=x2=...=xs=1). 
        // Lượng tổng bị sử dụng bởi s số này: s * (M + 1).
        // Lượng phần tử bị sử dụng bởi s số này: s * (M + 1)
 
        int total_value_removed = s * (M + 1); // Tổng bị "cố định"
        int total_parts_removed = s;           // Số lượng phần tử bị "cố định"
 
        int N_prime = N - total_value_removed; // Tổng còn lại để chia
        int K_prime = k - total_parts_removed;   // Số phần tử còn lại để chia
 
        // Nếu N_prime < K_prime, không thể chia được nữa
        if (N_prime < K_prime) break;
 
        // Số cách chọn s số x_i vi phạm (C(N, s) - Số cách chọn s giá trị khác nhau)
        // Số cách chọn s vị trí (trong k vị trí) để đặt s số vi phạm (C(k, s))
 
        // Quan trọng: Phải là số cách chọn s giá trị khác nhau (x1, x2, ...) từ N giá trị,
        // nhân với số cách sắp xếp các giá trị còn lại.
 
        // SỬ DỤNG CÔNG THỨC KHOA HỌC: 
        // Số cách chia N thành k số, trong đó 's' số bất kỳ lặp >= M+1 lần (tối thiểu)
        // Số cách: C(k, s) * C(N - s*(M+1) - 1, k - 1)
        // (Sai: Công thức này chỉ áp dụng cho trường hợp các số vi phạm là cùng 1 giá trị)
 
        // Đơn giản hóa đối xứng:
        // Giả sử ta chọn s vị trí (C(k, s)) và gán cho chúng s số vi phạm (ví dụ: tất cả là số 1)
 
        // CÔNG THỨC CHÍNH XÁC (Dựa trên DP trên tổng số lần xuất hiện):
        // Số cách chia N thành k số, mỗi số lặp >= M+1 lần
        // Tương đương với: C(k, s) * Số cách chia N' = N - s*(M+1) thành k số bất kỳ.
 
        // Số cách chia N' thành k số nguyên dương bất kỳ: C(N' - 1, k - 1)
        // Phép nhân: C(k, s) * C(N - s*(M+1) - 1, k - 1)
 
        // 1. Số cách chọn 's' vị trí trong 'k' phần tử: C(k, s)
        long long ways_to_choose_s = C[k][s];
 
        // 2. Số cách phân phối tổng còn lại (N - s*(M+1)) vào k phần tử
        // N_r = N - s*(M+1) (Tổng còn lại)
        // k_r = k (Số phần tử)
        // Số cách: C(N_r - 1, k - 1)
        int N_remaining = N - s * (M + 1);
        long long ways_to_partition = combinations(N_remaining, k); // C(N_remaining - 1, k - 1)
 
        long long term = ways_to_choose_s * ways_to_partition;
 
        // Nếu s lẻ thì trừ đi, nếu s chẵn thì cộng vào (Bao hàm - Loại trừ)
        if (s % 2 == 1) {
            result -= term;
        } else {
            result += term;
        }
    }
 
    return result;
}
 
void solve() {
 
 
 
    int N, M;
    // Đọc N và M từ file INP
    if (!(cin >> N >> M)) {
        cerr << "Lỗi đọc dữ liệu từ file INP." << endl;
        return;
    }
 
    // Tiền xử lý Tổ hợp
    precompute_combinations();
 
    // Chạy vòng lặp từ k = 1 đến N
    for (int k = 1; k <= N; ++k) {
        long long result_k = solve_for_k(k, N, M);
        cout << result_k << (k == N ? "" : " ");
    }
 
 
}
 
int main() {
    // Tăng tốc I/O
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
 
    solve();
 
    return 0;
}