제출 #1335445

#제출 시각아이디문제언어결과실행 시간메모리
1335445reverberatedevMagneti (COCI21_magneti)C++20
110 / 110
205 ms13380 KiB
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
#define DEBUG 1

#ifdef DEBUG
    #define OUT(x) cerr << (#x) << '=' << (x) << endl
    #define OUT2(c) cerr << (#c) << " = {"; for (auto it = (c).begin(); it != (c).end(); ++it) cerr << (it == (c).begin() ? "" : ", ") << *it; cerr << "}" << endl;
#else
    #define OUT(x)
    #define OUT2(c)
#endif

const int MAXN = 55;
const int MAXL = 1e4 + 5;
const int MOD = 1e9 + 7;

int n, l;
int r[MAXN];
int dp[2][MAXN][MAXL];
int C[MAXL + MAXN][MAXN];

int mul(int x, int y){
    return (x * y) % MOD;
}

int add(int x, int y){
    return (x + y) % MOD;
}

void precompute() {
    for (int i = 0; i < MAXL + MAXN; i++) {
        C[i][0] = 1;
        for (int j = 1; j <= min(i, MAXN - 1); j++) {
            C[i][j] = add(C[i - 1][j - 1], C[i - 1][j]);
        }
    }
}

bool ok(int i, int j, int k){
    return 0 <= i && i <= 1 && 0 <= j && j < MAXN && 0 <= k && k < MAXL;
}

void solve() {
    cin >> n >> l;
    for(int i = 1; i <= n; i++){
        cin >> r[i];
    }
    sort(r + 1, r + n + 1);

    precompute();

    dp[0][0][0] = 1;
    
    int x = 0;

    for(int i = 0; i < n; i++){
        int nx = x ^ 1;
        memset(dp[nx], 0, sizeof(dp[nx]));
        int rv = r[i + 1];
        for(int j = 0; j <= n; j++){
            for(int k = 0; k <= l; k++){
                if(ok(nx, j + 1, k + 1)) dp[nx][j + 1][k + 1] = add(dp[nx][j + 1][k + 1], mul(dp[x][j][k], j + 1));
                if(ok(nx, j, k + rv)) dp[nx][j][k + rv] = add(dp[nx][j][k + r[i + 1]], mul(dp[x][j][k], 2 * j));
                if(ok(nx, j - 1, k + 2 * rv - 1)) dp[nx][j - 1][k + 2 * rv - 1] = add(dp[nx][j - 1][k + 2 * rv - 1], mul(dp[x][j][k], j - 1));
            }
        }
        x = nx;
    }

    int ans = 0;
    for (int k = 1; k <= l; k++) {
        if (dp[x][1][k] == 0) continue;
        ans = add(ans, mul(dp[x][1][k], C[l - k + n][n]));
    }

    cout << ans;
}
 
signed main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    solve();
}
 
/*
Sort the n magnets by their radius
dp[i][j][k] = number of ways to arrange the first i magnets such that there are j fixed groups with total length k

Transition: We apply the magnet i + 1
We want to slot it somewhere from here

1. Make new group
dp[i + 1][j + 1][k + 1] += dp[i][j][k] * (j + 1)

2. Attach to left or right of a group
dp[i + 1][j][k + r] += dp[i][j][k] * 2j

3. Connect two groups
dp[i + 1][j - 1][k + 2r - 1] += dp[i][j][k] * (j - 1)

Answer:
Let's say we take length k, now we have l - k empty spaces to distribute between n + 1 slots

n bars, so
l - k + n choose n
*/
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...