1. 程式人生 > 其它 >動態規劃_備忘錄法_矩陣鏈乘問題

動態規劃_備忘錄法_矩陣鏈乘問題

人均4題

Codeforces Round #732 (Div. 2)

A - AquaMoon and Two Arrays

模擬

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
 
    int _;
    for (cin >> _; _; --_) {
        int n;
        cin >> n;
 
        vector<int> a(n), b(n);
        for (auto &i : a)
            cin >> i;
 
        vector<pair<int, int>> ans;
        stack<int> x, y;
        for (int i = 0; i < n; ++i) {
            cin >> b[i];
 
            if (a[i] < b[i])
                x.push(i);
            else if (a[i] > b[i])
                y.push(i);
        }
        while (!x.empty() && !y.empty()) {
            while (a[x.top()] < b[x.top()] && a[y.top()] > b[y.top()]) {
                ans.emplace_back(y.top(), x.top());
                ++a[x.top()];
                --a[y.top()];
            }
 
            if (a[x.top()] == b[x.top()])
                x.pop();
            if (a[y.top()] == b[y.top()])
                y.pop();
        }
 
        if (!x.empty() || !y.empty())
            cout << "-1\n";
        else {
            cout << ans.size() << '\n';
            for (auto &i : ans)
                cout << i.first + 1 << ' ' << i.second + 1 << '\n';
        }
    }
    return 0;
}

B - AquaMoon and Stolen String

不管怎麼交換,每個位置上每種字母的個數不會變

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
 
    int _;
    for (cin >> _; _; --_) {
        int n, m;
        cin >> n >> m;
 
        vector<vector<int>> cnt(m, vector<int>(26, 0));
        for (int i = 0; i < n; ++i) {
            string s;
            cin >> s;
 
            for (int j = 0; j < m; ++j)
                ++cnt[j][s[j] - 'a'];
        }
 
        for (int i = 1; i < n; ++i) {
            string s;
            cin >> s;
 
            for (int j = 0; j < m; ++j)
                --cnt[j][s[j] - 'a'];
        }
 
        for (int i = 0; i < m; ++i)
            for (int j = 0; j < 26; ++j)
                if (cnt[i][j] == 1)
                    cout << char('a' + j);
 
        cout << '\n';
    }
    return 0;
}

C - AquaMoon and Strange Sort

每個數最終的位置是個區間,切區間內數相同

不管怎麼交換,最後的方向只和最初位置和最終位置的步數差有關,奇數向左,反之亦然

向左的時候我們就要找一個區間內也是向左的一個數且二者距離差為奇數,即可交換,使得二者全部向右

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
 
    int _;
    for (cin >> _; _; --_) {
        int n;
        cin >> n;
 
        vector<pair<int, int>> a(n);
        for (int i = 0; i < n; ++i)
            cin >> a[i].first, a[i].second = i;
        sort(a.begin(), a.end());
 
        bool f = 0;
        for (int i = 0, j = 0; i < n && !f; i = j) {
            int val[2] = { 0, 0 };
            for (; j < n && a[i].first == a[j].first; ++j)
                if (abs(a[j].second - j) & 1)
                    ++val[j & 1];
            f = val[1] ^ val[0];
        }
        cout << (f ? "NO" : "YES") << '\n';
    }
    return 0;
}

D - AquaMoon and Chess

跳棋,只要是兩個相鄰的\(1\),就可以走到任何位置,

eg:
0 1 0 [1 1]

-> 0 1 [1 1] 0

-> 1 1 0 1 0 = [1 1] 0 1 0

發現了嗎,\([0 \ 1 \ 0]\)的相對位置沒變, 只是\([1 \ 1]\)插入到\(0\)的兩邊而已,是個組合數學

設有\(n\)\([1 \ 1]\)(不重疊),\(m\)\(0\),由於\(0\)的左右對稱,故答案為

\(ans = C^{n}_{n+m}\)

int fac[N], inv[N], facinv[N], _, n;

int C(int n, int m) {
    return (long long)fac[n] * facinv[m] % mod * facinv[n - m] % mod;
}

void init(int n) {
    fac[0] = fac[1] = facinv[0] = facinv[1] = inv[0] = inv[1] = 1;
    for (int i = 2; i <= n; ++i) {
        fac[i] = (long long)fac[i - 1] * i % mod;
        inv[i] = (long long)(mod - mod / i) * inv[mod % i] % mod;
        facinv[i] = (long long)facinv[i - 1] * inv[i] % mod;
    }
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);

    init(1e5);
    for (cin >> _; _; --_) {
        cin >> n;

        string s;
        cin >> s;

        int x = 0, y = 0;
        for (int i = 0, f = 0; i < n; ++i) {
            if (s[i] == '0')
                ++y, f = 0;
            else if (f)
                ++x, f = 0;
            else
                f = 1;
        }

        cout << C(x + y, x) << '\n';
    }
    return 0;
}