AtCoder Beginner Contest 242(C~E)

AB water question

C - 1111gal password

Question meaning: give N (\ (2\le N\le 1e6 \)) to find the number of \ (X \) satisfying the following conditions, which needs to be divided by the module (\ (998244353 \))

  • $X $is \ (N \) digits
  • For each digit of \ (X_1,X_2,...,X_N \)
    • \(1\le X_i \le 9\)
    • \(|X_i - X_{i+1}| \le 1\)

Idea:

emm, looking directly at the past, I know that it is an obvious number theory derivation problem. I wrote several groups casually. It is found that when the definition state \ (f_{i,j} \) represents the qualified number with the length of \ (I \), how many ending digits are \ (j \). The recurrence formula is as follows:

\[\begin{array}{c} f_{i, j}=f_{i-1, j-1}+f_{i-1, j}+f_{i-1, j+1} \\ f_{i, 0}=f_{i, 10}=0 \\ f_{1, j}=1 \end{array} \]

[AC Code]

const int N = 1e6 + 10, mod = 998244353;
ll n;
ll f[N][11];
int main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    cout << fixed << setprecision(20);
    cin >> n;
    for (int i = 1; i <= 9; i += 1) f[1][i] = 1;
    for (int j = 2; j <= n; j++) 
        for (int i = 1; i <= 9; i++)
            f[j][i] = (f[j - 1][i - 1] + f[j - 1][i] + f[j - 1][i + 1]) % mod;
    // Define the initial and end and initial values
    // {1,2,3,4,5}, accumulate(a[0], a[5],0ll) = 15
    cout << accumulate(f[n] + 1, f[n] + 10, 0ll) % mod;
}

D - ABC Transform

Meaning:

Given a string \ (S \) with a length of \ (N \), it is composed of three characters: A, B and C. each change will make all a in \ (S \) become BC, all B become CA and all C become AB. for example, ABC will become BCCAAB after one change. Now there are Q queries. Each query is to find the \ (k_i \) character of the original string \ (S \) after \ (t_i \) changes

analysis:

First of all, it can be seen that the length of a character after performing \ (t \) operations is easy to calculate, so let's turn the problem into what is the \ (k \) after performing \ (t \) operations on a character.

The above can be considered as recursion, that is, defining a function similar to \ (f(c,t,k) \) indicates what is the \ (k) th string obtained by the character \ (c \) performing \ (t \) operations. There is only one problem: \ (t(\le 1e18) \) is too large

It is observed that each operation doubles the length of the string, so after performing few operations, it becomes evaluating \ (f(c,t,1) \). However, after three operations, the first character is equivalent to no change, so the result can be obtained directly.

Update: I found that although the original idea is correct, it is a little around

Let $f(t,k) $be the \ (k_i \) character obtained after \ (t_i \) changes of the original \ (S \)

First, when \ (t=0 \), directly output \ (S_k \)

Secondly, when \ (t \not= 0 \), we need to know where \ (f(t,k) \) comes from

Sample

ABC ->
BCCAAB ->
CAABABBCBCCA

Using the method of classified discussion, it is not difficult to find

  • When $k\in {2m+1 | m\in Z} $(i.e. \ (k \) is odd), \ (f(t - 1, \frac{k + 1}2) \to f(t,k) \)
  • When $k\in {2m | m\in Z} $(i.e. \ (k \) is even), \ (f(t - 1, \frac{k}2) \to f(t,k) \)

How to change?

It can be a \ (g \) function:

inline char g(char ch, int x) { return (ch - 'A' + x) % 3 + 'A';}

However, if we recurse every time \ (t \) is still too large, it will explode directly. Then you can only move \ (k \)

Observe the first strings in the sample. They are rotated by a, B and C.

Using this property, when \ (k=0 \), we can directly find \ (f(t,0) = g(S.front(),t mod 3) \)

But the problem comes. Such an algorithm will certainly take the module of \ (K \) in case \ (k = 0... \)

Therefore, we change the number of \ (S \) to \ (0 \to N-1 \)

At this time:

  • When $k\in {2m+1 | m\in Z} $(i.e. \ (k \) is odd), \ (f(t - 1, \frac{k - 1}2) \to f(t,k) \)
  • When $k\in {2m | m\in Z} $(i.e. \ (k \) is even), \ (f(t - 1, \frac{k}2) \to f(t,k) \)

The code is easy to write

string s;
ll q, t, k;
inline char g(char ch, int x) { return (ch - 'A' + x) % 3 + 'A';}
char f(ll t, ll k) {
    if (!t) return s[k];
    if (!k) return g(s[0], t % 3);
    return g(f(t - 1, k >> 1), (k & 1) + 1);
}

int main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    cout << fixed << setprecision(20);
    cin >> s >> q;
    while (q --) {
        cin >> t >> k;
        cout << f(t, k - 1) << "\n";
    }
}

E - (∀x∀)

title fun

We can enumerate the length of the same prefix of two strings, and then fill in smaller characters for the string \ (X \) in the latter position, and then fill in any subsequent position.

  • It is necessary to judge whether the second half of \ (X \) is less than or equal to \ (S \) when the first half of \ (X \) is the same as \ (S \).
const int N = 1e6, mod = 998244353;
ll pw[N + 10] = {1};
string s;
int T, n;
int main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    cout << fixed << setprecision(20);
    for (int i = 1; i <= N; i += 1) pw[i] = pw[i - 1] * 26ll % mod;
    cin >> T;
    while (T--) {
        cin >> n >> s;
        s = "@" + s;
        int ans = 0;
        bool f = 1;
        for (int i = 1; i <= (n + 1) / 2; i++) {
            int a = s[i] - 'A', b = s[n + 1 - i] - 'A';
            ans = (ans + (ll)a * pw[(n + 1) / 2 - i]) % mod;
            f &= a <= b;
            f |= a < b;
        }
        cout << (ans + f) % mod << "\n";
    }
}

Added by vbcoach on Mon, 07 Mar 2022 09:47:58 +0200