Codeforces
CF Step
Youtube Linkedin Discord Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

Code

This submission is logically correct, but purposefully ignores modulo operations so that you can focus on the logic.

#include <bits/stdc++.h>
using namespace std;

int mod;

void solve(int n) {
    vector<vector<vector<int>>> dp(
        n + 2, vector<vector<int>>(n + 3, vector<int>(3, 0)));
    // dp[i][j][k] is the number of ways to delete j edges from the i-th prefix
    // such that the resulting graph contains k connected components.
    // Here, we are only utilizing k = 1 and k = 2.
    // It is implicitly assumed that in case of 2 connected components, the top
    // and bottom vertex of the i-th prefix are part of different connected
    // components.

    // For n = 1, if the vertical edge is removed, we have 2 connected comp.
    dp[1][1][2] = 1;

    // If it is not removed, we have 1 connected component.
    dp[1][0][1] = 1;

    for (int i = 1; i <= n; i++) {
        for (int j = 0; j <= n; j++) {
            // Case 1 : The current graph has 1 connected component.
            // The next graph can either retain this connected component.
            // by not deleting any incoming edge, or delete exactly one of
            // the incoming edge.
            dp[i + 1][j][1] += dp[i][j][1];
            dp[i + 1][j + 1][1] += 3 * dp[i][j][1];

            // Or, the next graph can split it into two connected components.
            // For this to be possible, the incoming vertical edge needs to be
            // deleted, along with exactly one of the top or bottom edge.
            dp[i + 1][j + 2][2] += 2 * dp[i][j][1];

            // Case 2 : The current graph has 2 connected components.
            // The next graph can either retain these 2 connected components
            // by removing the vertical edge.
            dp[i + 1][j + 1][2] += dp[i][j][2];

            // Or, the next graph can merge it back into a single connected
            // component by not deleting any incoming edges.
            dp[i + 1][j][1] += dp[i][j][2];
        }
    }

    for (int i = 1; i < n; i++) {
        cout << dp[n][i][1] << " ";
    }
    cout << endl;
}

int main() {
    int n;
    cin >> n >> mod;
    solve(n);
}
#include <bits/stdc++.h>
using namespace std;

int mod;

void inc(int &a, int b) {
    a += b;
    a %= mod;
}

int mult(int a, int b) {
    long long res = 1LL * a * b;
    res %= mod;
    return res;
}

void solve(int n) {
    vector<vector<vector<int>>> dp(
        n + 2, vector<vector<int>>(n + 3, vector<int>(3, 0)));
    // dp[i][j][k] is the number of ways to delete j edges from the i-th prefix
    // such that the resulting graph contains k connected components.
    // Here, we are only utilizing k = 1 and k = 2.
    // It is implicitly assumed that in case of 2 connected components, the top
    // and bottom vertex of the i-th prefix are part of different connected
    // components.

    // For n = 1, if the vertical edge is removed, we have 2 connected comp.
    dp[1][1][2] = 1;

    // If it is not removed, we have 1 connected component.
    dp[1][0][1] = 1;

    for (int i = 1; i <= n; i++) {
        for (int j = 0; j <= n; j++) {
            // Case 1 : The current graph has 1 connected component.
            // The next graph can either retain this connected component.
            // by not deleting any incoming edge, or delete exactly one of
            // the incoming edge.
            inc(dp[i + 1][j][1], dp[i][j][1]);
            inc(dp[i + 1][j + 1][1], mult(3, dp[i][j][1]));

            // Or, the next graph can split it into two connected components.
            // For this to be possible, the incoming vertical edge needs to be
            // deleted, along with exactly one of the top or bottom edge.
            inc(dp[i + 1][j + 2][2], mult(2, dp[i][j][1]));

            // Case 2 : The current graph has 2 connected components.
            // The next graph can either retain these 2 connected components
            // by removing the vertical edge.
            inc(dp[i + 1][j + 1][2], dp[i][j][2]);

            // Or, the next graph can merge it back into a single connected
            // component by not deleting any incoming edges.
            inc(dp[i + 1][j][1], dp[i][j][2]);
        }
    }

    for (int i = 1; i < n; i++) {
        cout << dp[n][i][1] << " ";
    }
    cout << endl;
}

int main() {
    int n;
    cin >> n >> mod;
    solve(n);
}

This submission is logically correct, but purposefully ignores modulo operations so that you can focus on the logic.

#include <bits/stdc++.h>
using namespace std;

int mod;

void solve(int n) {
    vector<vector<vector<int>>> dp(
        n + 1, vector<vector<int>>(n + 1, vector<int>(3, 0)));
    // dp[i][j][k] is the number of ways to delete j edges from the i-th prefix
    // such that the resulting graph contains k connected components.
    // Here, we are only utilizing k = 1 and k = 2.
    // It is implicitly assumed that in case of 2 connected components, the top
    // and bottom vertex of the i-th prefix are part of different connected
    // components.

    // For n = 1, if the vertical edge is removed, we have 2 connected comp.
    dp[1][1][2] = 1;

    // If it is not removed, we have 1 connected component.
    dp[1][0][1] = 1;

    for (int i = 2; i <= n; i++) {
        for (int j = 0; j <= n; j++) {
            // Case 1 : The previous graph had just 1 connected component.
            // You can either keep that connected component by not deleting
            // any edge, or deleting atmost one edge.
            dp[i][j][1] += dp[i - 1][j][1];
            if (j - 1 >= 0) {
                dp[i][j][1] += 3 * dp[i - 1][j - 1][1];
            }

            // Or, you can break it into 2 by deleting exactly two edges.
            // Note that one of these edge has to be the vertical edge, else
            // the previous connected components can never be joined again.
            if (j - 2 >= 0) {
                dp[i][j][2] += 2 * dp[i - 1][j - 2][1];
            }

            // Case 2 : The previous graph had 2 connected components.
            // You can either keep that connected component by removing the
            // vertical edge.
            if (j - 1 >= 0) {
                dp[i][j][2] += dp[i - 1][j - 1][2];
            }

            // Or, you can join it back to a single connnected component by not
            // removing any edge now.
            dp[i][j][1] += dp[i - 1][j][2];
        }
    }

    for (int i = 1; i < n; i++) {
        cout << dp[n][i][1] << " ";
    }
    cout << endl;
}

int main() {
    int n;
    cin >> n >> mod;
    solve(n);
}
#include <bits/stdc++.h>
using namespace std;

int mod;

void inc(int &a, int b) {
    a += b;
    a %= mod;
}

int mult(int a, int b) {
    long long res = 1LL * a * b;
    res %= mod;
    return res;
}

void solve(int n) {
    vector<vector<vector<int>>> dp(
        n + 1, vector<vector<int>>(n + 1, vector<int>(3, 0)));
    // dp[i][j][k] is the number of ways to delete j edges from the i-th prefix
    // such that the resulting graph contains k connected components.
    // Here, we are only utilizing k = 1 and k = 2.
    // It is implicitly assumed that in case of 2 connected components, the top
    // and bottom vertex of the i-th prefix are part of different connected
    // components.

    // For n = 1, if the vertical edge is removed, we have 2 connected comp.
    dp[1][1][2] = 1;

    // If it is not removed, we have 1 connected component.
    dp[1][0][1] = 1;

    for (int i = 2; i <= n; i++) {
        for (int j = 0; j <= n; j++) {
            // Case 1 : The previous graph had just 1 connected component.
            // You can either keep that connected component by not deleting
            // any edge, or deleting atmost one edge.
            inc(dp[i][j][1], dp[i - 1][j][1]);
            if (j - 1 >= 0) {
                inc(dp[i][j][1], mult(3, dp[i - 1][j - 1][1]));
            }

            // Or, you can break it into 2 by deleting exactly two edges.
            // Note that one of these edge has to be the vertical edge, else
            // the previous connected components can never be joined again.
            if (j - 2 >= 0) {
                inc(dp[i][j][2], mult(2, dp[i - 1][j - 2][1]));
            }

            // Case 2 : The previous graph had 2 connected components.
            // You can either keep that connected component by removing the
            // vertical edge.
            if (j - 1 >= 0) {
                inc(dp[i][j][2], dp[i - 1][j - 1][2]);
            }

            // Or, you can join it back to a single connnected component by not
            // removing any edge now.
            inc(dp[i][j][1], dp[i - 1][j][2]);
        }
    }

    for (int i = 1; i < n; i++) {
        cout << dp[n][i][1] << " ";
    }
    cout << endl;
}

int main() {
    int n;
    cin >> n >> mod;
    solve(n);
}