[Luo valley P5342] [TJOI2019] Mr segment tree toluene (digit dp)

Address

Luogu # 5342

Solution

  • For (C =. 1 \) \ , since the path length (O (d) \) \ level just know, (LCA (X, Y) \) \ is \ (x, y \) under binary \ (LCP \ ) it can be done.

  • For \ (c = 2 \) , first and \ (c = 1 \) as determined path number and then obviously a need to know the nature and the nature of a god:
    \ (. (1) \) Kee \ (x \) binary \ (1 \) number is \ (CNT (X) \) , then \ (X \) to the root and the path number for the \ (2x-CNT (X) \) . Note that this property is in the root \ (0 \) is also satisfied, as long as (x \) \ son or \ (2x, 2x 1 + \) .
    \ ((2). \) Number and the path is referred to as \ (S \) two endpoints path is \ (X, Y \) , \ (LCA (X, Y) = Z \) , \ (X → z \) to go through the \ (A \) edges, \ (Y → z \) to go through the \ (B \) edges. Then when (a, b, s \) \ When the values are set, \ (Z \) It shall be given value.

  • Consider proof properties \ ((2): \)
    the path \ (x → y (x < y) \) for each point written on binary numbers, their \ (LCP \) is \ (Z \) binary. Kee \ (z \) binary there \ (t \) position, then to calculate the point number before each \ (t \) contributions bit value. \ (z \) contribution \ (z \) , \ (z \) for each son's contribution is \ (2Z \) , the contribution of each grandchild is \ (4Z \) , and so on, you can get before the \ (T \) the total contribution bits \ (V \) is:
    \ (2Z + Z + 4Z + .... + 2 ^ {a} + Z + Z 2Z 4Z + 2 + ... + B ^ {} ZZ \)
    \ (= (2 ^ {+}. 1 A + B + 2 ^ {}. 1 -3) Z \)
  • Note \ (K \) is the contribution of the other, namely: \ (VZ + S = K \)
    discussed \ (K \) ranges (assume \ (A, B> 0 \) ): \
    (1. \ ) \ (Z \) go left \ (1 \) step, and then to the left to go \ (a-1 \) steps to \ (X \) ; \ (Z \) go right \ (1 \) step, then to the left to go \ (b-1 \) steps to \ (the y-\) . Path \ (x → z \) of \ (K \) contribute to the \ (0 \) , \ (Y → Z \) of \ (K \) contribute to the \ (2 ^ B-. 1 \) , this when \ (K \) takes the most small value.
    \ (2. \) \ (Z \)Go left \ (1 \) step, and then to the right down \ (a-1 \) steps to \ (X \) ; \ (Z \) go right \ (1 \) step, and then to the right down \ ( b-1 \) steps to \ (Y \) . Path \ (x → z \) of \ (K \) contribute to the \ (2 ^ AA-. 1 \) , \ (Y → Z \) of \ (K \) contribute to the \ (2 ^ {b + } -b-2. 1 \) , this time \ (K \) take the most large value.
    In summary, \ (k∈ [1,2-B ^ 2 + 2 ^ A ^ B +. 1 {}. 3--ab] \) .
  • We found \ (K <V \) , then the \ (Z = S / V, K = S \% V \) , \ (V \) values only and \ (a, b \) are, therefore \ (Z \ ) is constant, proof.
  • The question then is converted to: find the two numbers \ (P, Q \) (that is, \ (x, y \) before cut \ (T \) value after bits, the first cut \ (T \) posterior, \ (X \) most significant bit is \ (0 \) , \ (Y \) most significant bit is \ (. 1 \) ), \ (P <2 ^ {A-. 1}, Q <2 ^ B, 2 (P + Q) -CNT (P) -CNT (Q) = K \) , attention \ (Q \) a \ (2 ^ {b-1 } \) bits must be \ (1 \) .
  • Enumeration \ (CNT (P) + CNT (Q) \) , to give \ (A + B = W \) , do the digit \ (DP \) , \ (F [I] [J] [K = 0 /. 1 ] \) represents (from bits start \ (a, b \) simultaneously fill), filled \ (I \) bits, then a total fill \ (J \) a \ (1 \) , whether the carry to the first \ (i + 1 \) bits requires \ (a + b \) of each bit and \ (W \) of the can.
  • Attention to detailAttention to open \ (Long \) \ (Long \) , attention high tree (a, b, z \) \ limit value.
  • Time complexity \ (O (D ^. 5) \) , apparently very small constant.

    Code

#include <bits/stdc++.h>

using namespace std;

#define ll long long

template <class t>
inline void read(t & res)
{
    char ch;
    while (ch = getchar(), !isdigit(ch));
    res = ch ^ 48;
    while (ch = getchar(), isdigit(ch))
    res = res * 10 + (ch ^ 48);
}

template <class t>
inline void print(t x)
{
    if (x > 9) print(x / 10);
    putchar(x % 10 + 48);
}

const int e = 205;
ll f[e][e][2], ans;
bool a1[e], b1[e];

inline ll dp(int a, int b, ll s, int c)
{
    int i, j, t, x, y, bit = max(max(a - 1, b), (int)log2(s) + 1) + 1; 
    bool flag = a == 3 && b == 2;
    for (i = 0; i < bit; i++)
    for (j = 0; j <= c; j++)
    f[i][j][0] = f[i][j][1] = 0;
    i = 0;
    for (x = 0; x <= 1; x++)
    for (y = 0; y <= 1; y++)
    {
        int k = x + y >> 1, z = x + y & 1;
        if (i == b - 1 && !y) continue;
        if (z != (s & 1)) continue;
        if (i > b - 1 && y) continue;
        if (i > a - 2 && x) continue;
        f[0][x + y][k]++;
    }
    for (i = 0; i < bit - 1; i++)
    {
        ll d = s & (1ll << i + 1);
        if (d) d = 1;
        for (j = 0; j <= c; j++)
        for (t = 0; t <= 1; t++)
        if (f[i][j][t])
        for (x = 0; x <= 1; x++)
        for (y = 0; y <= 1; y++)
        {
            int now = x + y + t, k = now >> 1, z = now & 1;
            if (i + 1 == b - 1 && !y) continue;
            if (z != d) continue;
            if (i + 1 > b - 1 && y) continue;
            if (i + 1 > a - 2 && x) continue;
            f[i + 1][j + x + y][k] += f[i][j][t];
        }
    }
    return f[bit - 1][c][0];
}

inline ll calc(ll x)
{
    ll res = x << 1;
    while (x) res -= x & 1, x >>= 1;
    return res;
}

int main()
{
    int i, lx, ly, op, tst, h;
    ll x, y, z;
    read(tst);
    while (tst--)
    {
        read(h); read(x); read(y); read(op);
        ll x2 = x, y2 = y;
        lx = ly = z = 0;
        while (x) a1[++lx] = x & 1, x >>= 1;
        while (y) b1[++ly] = y & 1, y >>= 1;
        reverse(a1 + 1, a1 + lx + 1);
        reverse(b1 + 1, b1 + ly + 1);
        for (i = 1; i <= lx && i <= ly; i++)
        if (a1[i] == b1[i]) z = z * 2 + a1[i];
        else break;
        ll s = calc(x2) + calc(y2) - calc(z) - calc(z >> 1);
        if (op == 1)
        {
            print(s);
            putchar('\n');
            continue;
        }
        ans = 0;
        for (int a = 0; a < h; a++)
        for (int b = 0; b < h; b++)
        {
            ll y = ((1ll << a + 1) + (1ll << b + 1) - 3), x = s / y;
            if (!x) continue;
            if ((int)log2(x) + 1 + max(a, b) > h) continue;
            ll k = s - x * y;
            for (int c = 0; c <= a + b; c++) 
            if ((k + c) % 2 == 0) ans += dp(a, b, k + c >> 1, c);
        }
        print(ans - 1);
        putchar('\n');
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/cyf32768/p/12196242.html