Atcoder beginer contest 232 (E, f supplement)

Posted by atravotum on Tue, 21 Dec 2021 21:18:29 +0100

E - Rook Path

Meaning:

Given size is H × W H×W H × W matrix, you now have a car (you can walk any distance in one direction in the matrix), and now the starting point is ( x 1 , y 1 ) (x_1,y_1) (x1, y1), end point ( x 2 , y 2 ) (x_2,y_2) (x2, y2), you can only move exactly now k k k times, what is the number of schemes moving from the starting point to the end point?

Idea:

Define one for horizontal and one for vertical d p dp dp equation regards a two-dimensional movement as two one-dimensional movements, which are defined as X ( i , 0 / 1 ) , Y ( i , 0 / 1 ) X(i,0/1),Y(i,0/1) X(i,0/1),Y(i,0/1)
with X ( i , 0 / 1 ) X(i,0/1) Taking X(i,0/1) as an example, it represents the movement i i Number of schemes that have reached the end point after i times (only considered) x x x-axis), 0 0 0 means no arrival, 1 1 1 represents arrival
Then the state transition equation
X ( i , 1 ) = X ( i − 1 , 0 ) X(i,1)=X(i-1,0) X(i,1)=X(i−1,0)
X ( i , 0 ) = X ( i − 1 , 0 ) × ( n − 2 ) + X ( i − 1 , 1 ) × ( n − 1 ) X(i,0)=X(i-1,0)×(n-2)+X(i-1,1)×(n-1) X(i,0)=X(i−1,0)×(n−2)+X(i−1,1)×(n−1)
Y Y Y same principle
The last step is to traverse all the X ( i , 1 ) and Y ( k − i , 1 ) X(i,1) and Y(k-i,1) X(i,1) and Y(k − i,1), multiply the two one-dimensional schemes by a combinatorial number C k i C^i_k Cki to determine the moving order of the two one-dimensional schemes

#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;
const int N = 1e6 + 10;
const int mod = 998244353;
#define ll long long
int n, m, k, X1, Y1, X2, Y2;
ll x[N][2], y[N][2], fact[N], infact[N];
ll qmi(int a, int k, int p) {
    ll res = 1;
    while (k) {
        if (k & 1) res = (ll)res * a % p;
        k >>= 1;
        a = (ll)a * a % p;
    }
    return res;
}
void Init() {
    fact[0] = infact[0] = 1;
    for (int i = 1; i < N; i++) {
        fact[i] = (ll)fact[i - 1] * i % mod;
        infact[i] = (ll)infact[i - 1] * qmi(i, mod - 2, mod) % mod;
    }
}

ll C(int a, int b) {
    if (a < b) return 0;
    return fact[a] * infact[b] % mod * infact[a - b] % mod;
}

int main() {
    Init();
    scanf("%d%d%d", &n, &m, &k);
    scanf("%d%d%d%d", &X1, &Y1, &X2, &Y2);

    if (X1 != X2) {
        x[0][0] = 1;
    } else {
        x[0][1] = 1;
    }
    if (Y1 != Y2) {
        y[0][0] = 1;
    } else {
        y[0][1] = 1;
    }
    for (int i = 1; i <= k; i++) {
        (x[i][1] += x[i - 1][0]) %= mod;
        x[i][0] += (x[i - 1][1] * (n - 1) % mod + x[i - 1][0] * (n - 2) % mod) % mod;
        x[i][0] %= mod;

        (y[i][1] += y[i - 1][0]) %= mod;
        y[i][0] += (y[i - 1][1] * (m - 1) % mod + y[i - 1][0] * (m - 2) % mod) % mod;
        y[i][0] %= mod;
    }

    ll res = 0;

    for (int i = 0; i <= k; i++) {
        ll temp = x[i][1] * y[k - i][1] % mod;
        res += temp * C(k, i) % mod;
        res %= mod;
    }
    printf("%lld\n", res);
}

F - Simple Operations on Sequence

Meaning:

Given two lengths N N N A A A sequence and B B B sequence, now there are 2 2 2 operations
1. 1. 1. Make A i A_i Ai increase 1 1 1 or decrease 1 1 1. Consumption required X X X Yuan
2. 2. 2. Exchange A i A_i Ai and A i + 1 A_{i+1} The position of Ai+1 , needs to be consumed Y Y Y yuan
It can be operated many times. Ask how much it takes to make A A A sequence becomes B B B sequence

Idea:

The sequence length is very small, only 18 18 18, so state compression can be considered
Suppose now A A The number in A sequence is i i i have been identified and become B B Front in B i i i, of course, can also be reversed, which is equivalent.
So how do you express it now A A Which one in A i i The number of i has been determined, that is, through binary, that is, state compression, through 1 1 1 to indicate which numbers have been determined. At this time, you only need to enumerate, and then determine the number, and this number cannot be determined in the current state. At this time, the enumeration is the second i + 1 i+1 i+1, then the price at this time is ∣ A [ i + 1 ] − B [ j ] ∣ × X + c n t × Y |A[i+1]-B[j]|×X+cnt×Y ∣A[i+1]−B[j]∣×X+cnt×Y, c n t cnt cnt is B j B_j Bj# move to A i + 1 A_{i+1} The number of times the Ai+1} position needs to be exchanged.
So the hypothetical state is s t a t e state state, c n t S cntS cntS is the number of definite numbers, and the enumerator is B j B_j Bj​, c n t cnt cnt is a
f ( s t a t e ∣ 1 < < ( j − 1 ) ) = m i n ( f ( s t a t e ∣ 1 < < ( j − 1 ) ) , f ( s t a t e ) + ∣ A [ i + 1 ] − B [ j ] ∣ × X + c n t × Y ) f(state|1<<(j-1))=min(f(state|1<<(j-1)),f(state)+|A[i+1]-B[j]|×X+cnt×Y) f(state∣1<<(j−1))=min(f(state∣1<<(j−1)),f(state)+∣A[i+1]−B[j]∣×X+cnt×Y)
According to the subscript is from 0 0 0 or 1 1 1 start by adjusting the subscript

For example,

#include <bits/stdc++.h>
using namespace std;
const int N = 1 << 18;
#define ll long long
const ll inf = 2e18;
int n;
ll a[30], b[30];
ll f[N], x, y;
bool c[30];
ll F(int state, int now) {
    int res = 0;
    for (int i = 1; i <= n; i++) {
        if ((state & (1 << (i - 1))) == 0 && i < now) res++;
    }
    return res;
}
int main() {
    scanf("%d%lld%lld", &n, &x, &y);
    for (int i = 1; i <= n; i++) {
        scanf("%lld", &a[i]);
    }
    for (int i = 1; i <= n; i++) {
        scanf("%lld", &b[i]);
    }
    f[0] = 0;
    for (int i = 1; i < (1 << n); i++) {
        f[i] = inf;
    }

    for (int state = 0; state < (1 << n); state++) {
        int cntS = 0;
        for (int j = 1; j <= n; j++) {
            if (state & (1 << (j - 1))) {
                cntS++;
            }
        }

        for (int j = 1; j <= n; j++) {
            if (state & (1 << (j - 1))) continue;
            f[state | (1 << (j - 1))] = min(f[state | (1 << (j - 1))], f[state] + abs(a[cntS + 1] - b[j]) * x + F(state, j) * y);
        }
    }
    printf("%lld\n", f[(1 << n) - 1]);
}

To be continued
If you have any suggestions or criticisms and additions, please leave a message and point it out. Thank you very much

Topics: Dynamic Programming atcoder