Submission #1325829

#TimeUsernameProblemLanguageResultExecution timeMemory
1325829pfangNoM (RMI21_nom)C++20
100 / 100
40 ms540 KiB
#include <bits/stdc++.h>

using namespace std;

#define int long long

// has to be DP:
// most probably dp[i][j] for n^2 solution 
// buckets modulo M: each bucket is 0 to M-1, the positions of the stones must not be in the same bucket 
// pair up 2n positions into n pairs: 1 from 1 bucket, other form other bucket
// we can match up positions, then multiply by n! (for each different possible config )
// and 2^n for switching stone color 
// should be dp: 
// from using positions from 0 to i 
// j is amount of stuff left over from previous buckets: we can get at most j + 1 things from the current bucket to pair off 
// transition may take too long

const int MOD = 1e9 + 7;
const int MAXN = 4005;

int powmod(int a, int b){
    int res = 1;
    while(b){
        if(b & 1){
            res = res * a % MOD;
        }
        a = a*a % MOD;
        b >>= 1;
    }
    return res;
}

int factorial[MAXN], invfact[MAXN];

int C(int n, int k){
    if(k < 0 || k > n){
        return 0;
    }
    return (factorial[n] * ((invfact[k] * invfact[n-k])%MOD))%MOD;
}

int32_t main(){
    int n, m;
    cin >> n >> m;
    int tot = 2*n;
    vector<int> mods(m, 0);
    for(int i = 1; i <= tot; i++){
        mods[i % m]++;
    }
    sort(mods.begin(), mods.end());
    factorial[0] = 1;
    for(int i = 1; i <= tot; i++){
        factorial[i] = factorial[i-1] * i % MOD;
    }
    invfact[tot] =powmod(factorial[tot], MOD - 2);
    for(int i = tot; i > 0; i--){
        invfact[i-1] = invfact[i] * i % MOD;
    }
    vector<int> dp(tot+1, 0), ndp(tot + 1, 0);
    dp[0] = 1;
    int processed = 0;
    for(int i = 0; i < m; i++){
        int bucket = mods[i];
        if(bucket == 0){
            continue;
        }
        fill(ndp.begin(), ndp.end(), 0);
        for(int j = 0; j <= processed; j++){
            if(dp[j] == 0){
                continue;
            }
            for(int k = 0; k <= min(k, bucket); k++){
                int nj = j + bucket - 2 * k;
                int remaining = tot - (processed + bucket);
                if(nj > remaining){
                    continue; // doesnt work 
                }
                int ways = dp[j];
                ways *= C(j, k);
                ways %= MOD;
                ways *= C(bucket, k);
                ways %= MOD;
                ways *= factorial[k];
                ways %= MOD;
                ndp[nj] += ways;
                ndp[nj] %= MOD;
            }
        }
        processed += bucket;
        dp.swap(ndp);
    }
    int ans = dp[0];
    ans *= factorial[n];
    ans %= MOD;
    ans *= powmod(2, n);
    ans %= MOD;
    cout << ans << '\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...
#Verdict Execution timeMemoryGrader output
Fetching results...