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