QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#451490#8529. Balance of PermutationHKOI0#WA 0ms12200kbC++2011.2kb2024-06-23 15:03:152024-06-23 15:03:18

Judging History

你现在查看的是最新测评结果

  • [2024-06-23 15:03:18]
  • 评测
  • 测评结果:WA
  • 用时:0ms
  • 内存:12200kb
  • [2024-06-23 15:03:15]
  • 提交

answer

#include <bits/stdc++.h>
#define sz(v) (int)v.size()
#define all(v) v.begin(), v.end()

using namespace std;
using ll = long long;
using pii = pair<int, int>;
using vi = vector<int>;
// #define int __int128_t
using i128 = __int128;

istream& operator>> (istream& in, __int128_t& x){
    string s; in >> s;
    x = 0; for (auto c : s) x = x * 10 + c - '0';
    return in;
}

ostream& operator<< (ostream& out, __int128_t x){
    string s; while (x) s.push_back('0' + x % 10), x /= 10; if (s.empty()) s = "0";
    reverse(all(s)); return out << s;
}

template<typename T> void chadd(T& x, T y){ x += y; }

const int B = 450 + 11;
i128 dp[31][31][B * 2];
i128 dp2[31][31][B * 2];
bool ok_a[31], ok_b[31];
i128 countPerm(int n, vector<int>& p, int len, int b){
    fill(ok_a + 1, ok_a + 31, true); fill(ok_b, ok_b + 31, true);
    fill(ok_a + 1, ok_a + 1 + len, false); for (int i = 0; i < len; i++) ok_b[p[i]] = false;
    // for (int i = 1; i <= n; i++) {
    //     cout << ok_a[i] << ' ';
    // }
    // cout << endl;
    // for (int i = 1; i <= n; i++) {
    //     cout << ok_b[i] << ' ';
    // }
    // cout << endl;
    
    for (int r = 0; r <= 0; r++) {
        for (int b = 0; b < B * 2; b++) {
            dp[r][0][b] = dp[0][r][b] = 0;
        }
    }
    dp[0][0][B] = 1;
    int bl = B, br = B;
    for (int i = 0; i < n; i++) {
        for (int r = 0; r <= i + 1; r++) {
            for (int b = 0; b < B * 2; b++) {
                dp[r][i + 1][b] = dp[i + 1][r][b] = 0;
            }
        }
        auto copy_and_clear = [&] () {
            for (int rem_a = 0; rem_a <= i + 1; rem_a++) {
                for (int rem_b = 0; rem_b <= i + 1; rem_b++) {
                    for (int balance = bl; balance <= br; balance++) {
                        dp2[rem_a][rem_b][balance] = dp[rem_a][rem_b][balance];
                        dp[rem_a][rem_b][balance] = 0;
                    }
                }
            }
        };

        auto valid_balance = [&] (int x) {
            return 0 <= x && x < B * 2;
        };

        // top row
        if (ok_a[i + 1]) {
            copy_and_clear();
            for (int rem_a = 0; rem_a <= i; rem_a++) {
                for (int rem_b = 0; rem_b <= i; rem_b++) {
                    for (int balance = bl; balance <= br; balance++) {
                        i128 old_val = dp2[rem_a][rem_b][balance];
                        if (!old_val) continue;
                        // match backwards
                        if (rem_b && valid_balance(balance + (i + 1))) {
                            chadd(dp[rem_a][rem_b - 1][balance + (i + 1)], old_val * rem_b);
                        }
                        // match forwards
                        if (valid_balance(balance - (i - 1))) {
                            chadd(dp[rem_a + 1][rem_b][balance - (i + 1)], old_val);
                        }
                    }
                }
            }
            bl -= (i + 1); br += (i + 1);
            bl = max(0, bl);
            br = min(B * 2 - 1, br);
        }
        // printf("Half\n");
        // for (int r = 0; r <= i + 1; r++) {
        //     for (int s = 0; s <= i + 1; s++) {
        //         for (int b = 0; b < B * 2; b++) {
        //             if (dp[r][s][b]) {
        //                 printf("dp[%lld][%lld][%lld][%lld] = %lld\n", (int64_t) (i + 1), (int64_t) r, (int64_t) s, (int64_t) b, (int64_t) dp[r][s][b]);
        //             }
        //         }
        //     }
        // }
        // bottom row
        if (ok_b[i + 1]) {
            copy_and_clear();
            for (int rem_a = 0; rem_a <= i; rem_a++) {
                for (int rem_b = 0; rem_b <= i; rem_b++) {
                    for (int balance = bl; balance <= br; balance++) {
                        i128 old_val = dp2[rem_a][rem_b][balance];
                        if (!old_val) continue;
                        // if (old_val) cout << rem_a << ' ' << rem_b << ' ' << balance << endl;
                        // match backwards
                        if (rem_a && valid_balance(balance + (i + 1))) {
                            chadd(dp[rem_a - 1][rem_b][balance + (i + 1)], old_val * rem_a);
                        }
                        // match forwards
                        if (valid_balance(balance - (i - 1))) {
                            chadd(dp[rem_a][rem_b + 1][balance - (i + 1)], old_val);
                        }
                    }
                }
            }
            bl -= (i + 1); br += (i + 1);
            bl = max(0, bl);
            br = min(B * 2 - 1, br);
        }
        // printf("End\n");
        // for (int r = 0; r <= i + 1; r++) {
        //     for (int s = 0; s <= i + 1; s++) {
        //         for (int b = 0; b < B * 2; b++) {
        //             if (dp[r][s][b]) {
        //                 printf("dp[%lld][%lld][%lld][%lld] = %lld\n", (int64_t) (i + 1), (int64_t) r, (int64_t) s, (int64_t) b, (int64_t) dp[r][s][b]);
        //             }
        //         }
        //     }
        // }
    }

    // for (int i = B - b; i <= B + b; i++) {
    //     cout << dp[n][0][0][i] << ' ';
    // }
    // cout << endl;
    // cout << "RESULT " << dp[n][0][0][B + b] << endl;
    return dp[0][0][B + b];
}

int64_t dp_64[31][31][B * 2];
int64_t dp2_64[31][31][B * 2];
i128 countPerm_64(int n, vector<int>& p, int len, int b){
    fill(ok_a + 1, ok_a + 31, true); fill(ok_b, ok_b + 31, true);
    fill(ok_a + 1, ok_a + 1 + len, false); for (int i = 0; i < len; i++) ok_b[p[i]] = false;
    // for (int i = 1; i <= n; i++) {
    //     cout << ok_a[i] << ' ';
    // }
    // cout << endl;
    // for (int i = 1; i <= n; i++) {
    //     cout << ok_b[i] << ' ';
    // }
    // cout << endl;
    
    for (int r = 0; r <= 0; r++) {
        for (int b = 0; b < B * 2; b++) {
            dp_64[r][0][b] = dp_64[0][r][b] = 0;
        }
    }
    dp_64[0][0][B] = 1;
    int bl = B, br = B;
    for (int i = 0; i < n; i++) {
        for (int r = 0; r <= i + 1; r++) {
            for (int b = bl; b <= br; b++) {
                dp_64[r][i + 1][b] = dp_64[i + 1][r][b] = 0;
            }
        }
        auto copy_and_clear = [&] () {
            for (int rem_a = 0; rem_a <= i + 1; rem_a++) {
                for (int rem_b = 0; rem_b <= i + 1; rem_b++) {
                    for (int balance = bl; balance <= br; balance++) {
                        dp2_64[rem_a][rem_b][balance] = dp_64[rem_a][rem_b][balance];
                        dp_64[rem_a][rem_b][balance] = 0;
                    }
                }
            }
        };

        auto valid_balance = [&] (int x) {
            return 0 <= x && x < B * 2;
        };

        // top row
        if (ok_a[i + 1]) {
            copy_and_clear();
            for (int rem_a = 0; rem_a <= i; rem_a++) {
                for (int rem_b = 0; rem_b <= i; rem_b++) {
                    for (int balance = bl; balance <= br; balance++) {
                        int64_t old_val = dp2_64[rem_a][rem_b][balance];
                        if (!old_val) continue;
                        // match backwards
                        if (rem_b && valid_balance(balance + (i + 1))) {
                            chadd(dp_64[rem_a][rem_b - 1][balance + (i + 1)], old_val * rem_b);
                        }
                        // match forwards
                        if (valid_balance(balance - (i - 1))) {
                            chadd(dp_64[rem_a + 1][rem_b][balance - (i + 1)], old_val);
                        }
                    }
                }
            }
            bl -= (i + 1); br += (i + 1);
            bl = max(0, bl);
            br = min(B * 2 - 1, br);
        }
        // printf("Half\n");
        // for (int r = 0; r <= i + 1; r++) {
        //     for (int s = 0; s <= i + 1; s++) {
        //         for (int b = 0; b < B * 2; b++) {
        //             if (dp_64[r][s][b]) {
        //                 printf("dp_64[%lld][%lld][%lld][%lld] = %lld\n", (int64_t) (i + 1), (int64_t) r, (int64_t) s, (int64_t) b, (int64_t) dp_64[r][s][b]);
        //             }
        //         }
        //     }
        // }
        // bottom row
        if (ok_b[i + 1]) {
            copy_and_clear();
            for (int rem_a = 0; rem_a <= i; rem_a++) {
                for (int rem_b = 0; rem_b <= i; rem_b++) {
                    for (int balance = bl; balance <= br; balance++) {
                        int64_t old_val = dp2_64[rem_a][rem_b][balance];
                        if (!old_val) continue;
                        // if (old_val) cout << rem_a << ' ' << rem_b << ' ' << balance << endl;
                        // match backwards
                        if (rem_a && valid_balance(balance + (i + 1))) {
                            chadd(dp_64[rem_a - 1][rem_b][balance + (i + 1)], old_val * rem_a);
                        }
                        // match forwards
                        if (valid_balance(balance - (i - 1))) {
                            chadd(dp_64[rem_a][rem_b + 1][balance - (i + 1)], old_val);
                        }
                    }
                }
            }
            bl -= (i + 1); br += (i + 1);
            bl = max(0, bl);
            br = min(B * 2 - 1, br);
        }
        // printf("End\n");
        // for (int r = 0; r <= i + 1; r++) {
        //     for (int s = 0; s <= i + 1; s++) {
        //         for (int b = 0; b < B * 2; b++) {
        //             if (dp_64[r][s][b]) {
        //                 printf("dp_64[%lld][%lld][%lld][%lld] = %lld\n", (int64_t) (i + 1), (int64_t) r, (int64_t) s, (int64_t) b, (int64_t) dp_64[r][s][b]);
        //             }
        //         }
        //     }
        // }
    }

    // for (int i = B - b; i <= B + b; i++) {
    //     cout << dp_64[n][0][0][i] << ' ';
    // }
    // cout << endl;
    // cout << "RESULT " << dp_64[n][0][0][B + b] << endl;
    return dp_64[0][0][B + b];
}

void solve() {
    int n, b;
    i128 k;
    cin >> n >> b >> k;
    vector<int> p(n);
    vector<bool> rem(n + 1, true);
    for (int i = 0; i < n; i++) {
        for (int j = 1; j <= n; j++) {
            if (!rem[j]) continue;
            // cout << "POSITION " << i << " VALUE " << j << " => K " << k << endl;
            p[i] = j;
            vector<int> x(p.begin(), p.begin() + i + 1);
            vector<int> y; 
            i128 cp;
            if (n - i > 16) {
                cp = countPerm(n, p, i + 1, b - ((i + 1) - j < 0 ? j - (i + 1) : (i + 1) - j));
            } else {
                cp = countPerm_64(n, p, i + 1, b - ((i + 1) - j < 0 ? j - (i + 1) : (i + 1) - j));
            }
            if (k <= cp) {
                rem[j] = false;
                b -= ((i + 1) - j < 0 ? j - (i + 1) : (i + 1) - j);
                break;
            } else {
                k -= cp;
            }
        }
    }
    for (int i = 0; i < n; i++) {
        cout << p[i] << ' ';
    }
    cout << '\n';
}

signed main() {
#ifndef LOCAL
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
#endif
    int T = 1;
    // cin >> T;
    while (T--) solve();
    return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 0
Wrong Answer
time: 0ms
memory: 12200kb

input:

6 6 6

output:

1 2 3 4 6 6 

result:

wrong answer 3rd numbers differ - expected: '6', found: '3'