"2019 Jizhong training Day21" problem-solving report

T1, digital

Note \ (S_I \) shows a \ (1 \) to \ (I \) string obtained sequentially connected;
\ (T \ (T \ ^ 10 Leq. 4) \) group query, each output enable \ (n- \ (n \ leq 10 ^ { 18}) \) as occurs in the substring \ (s_x \) smallest \ (X \) .

\(Sol\)

Sucker title
Only three cases:
. 1, \ (n-X = \) ;
2, \ (n-\) is divided into two parts, the first part of \ (x - 1 \) suffix, the latter half of \ (X \) of prefix;
. 3, \ (n-\) is divided into several parts, there are several completely appear in the \ (n-\) in.
He loved big simulation, the code is unreadable.
See readable code here .

Time complexity \ (O (T \ LOG_. 3 ^ {n-10}) \) .

$Source:

#include <cstdio>
#include <algorithm>
int in() {
    int x = 0; char c = getchar(); bool f = 0;
    while (c < '0' || c > '9')
        f |= c == '-', c = getchar();
    while (c >= '0' && c <= '9')
        x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    return f ? -x : x;
}
long long lin() {
    long long x = 0; char c = getchar(); bool f = 0;
    while (c < '0' || c > '9')
        f |= c == '-', c = getchar();
    while (c >= '0' && c <= '9')
        x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    return f ? -x : x;
}
template<typename T>inline void chk_min(T &_, T __) { _ = _ < __ ? _ : __; }
template<typename T>inline void chk_max(T &_, T __) { _ = _ > __ ? _ : __; }

long long n, Pow[105];
int nn;

//Devide into 3 parts begin
long long calc(const int len) {
    int sub_len;
    bool flag;
    long long tmp, min = 1ll << 60ll;
    for (int i = nn, j, k; i + len > nn && i - len >= 0; --i) {
        long long now = n / Pow[nn - i] % Pow[len];
        tmp = now;
        flag = 0;
        if (i != nn) {
            ++tmp;
            sub_len = len + (tmp == Pow[len]);
            if (!(n % Pow[nn - i] / Pow[nn - i - 1]) || tmp / Pow[sub_len - (nn - i)] != n % Pow[nn - i])
                flag = 1;
        }
        if (flag == 1)
            continue;
        j = i, k = len;
        while (now && j - k > 0) {
            if (!(now / Pow[k - 1]) || now != n / Pow[nn - j] % Pow[k]) {
                flag = 1;
                break;
            }
            j -= k;
            if (now == Pow[k - 1])
                --k;
            --now;
        }
        if (j) {
            if (n / Pow[nn - j] != now % Pow[j])
                flag = 1;
        }
        if (!flag) {
            chk_min(min, tmp);
        }
    }
    return min;
}
//Devide into 3 parts end

int main() {
    //freopen("in", "r", stdin);
    freopen("number.in", "r", stdin);
    freopen("number.out", "w", stdout);
    int T = in();
    long long res;
    Pow[0] = 1;
    for (int i = 1; i <= 17; ++i)
        Pow[i] = Pow[i - 1] * 10;
    while (T--) {
        long long tmp;
        n = res = tmp = lin(), nn = 0;
        while (tmp)
            tmp /= 10, ++nn;
        tmp = n;
        //Devide into 2 parts begin
        for (int i = 1; i < nn; ++i) {
            if (n % Pow[nn - i] / Pow[nn - i - 1]) {
                for (int j = std::max(i, nn - i); j < nn; ++j) {
                    if (n % Pow[nn - j] == (n / Pow[nn - i] + 1) % Pow[i] / Pow[i - (nn - j)]) {
                        chk_min(res, (n / Pow[nn - i] + 1) % Pow[i] + n % Pow[nn - i] / Pow[nn - j] * Pow[i]);
                    }
                }
                chk_min(res, (n / Pow[nn - i] + 1) % Pow[i] + n % Pow[nn - i] * Pow[i]);
            }
        }
        //Devide into 2 parts end
        for (int i = 1; tmp; ++i, tmp /= 10) {
            chk_min(res, calc(i));
        }
        printf("%lld\n", res);
    }
    return 0;
}

T2 May

Topic Link

Given a \ (n \ times m \ ( n, m \ leq 100) \) four Unicom mesh arriving \ ((i, j) \ ) can be obtained \ (C_ {i, j} \ (0 \ leq C_ {i, j} \ leq 10 ^ 9) \) score (repeatedly get);
given starting point for \ ((a, B) \ (1 \ leq a \ leq n, 1 \ leq B \ leq m) \) , find just take (k \ (k \ leq 10 ^ 9) \ \) after the step back to the beginning of the maximum score.
Ensure \ (2 | K \) , \ (C_ {I, J} = 0 \) .

\(Sol\)

Since \ (k \) is large, the optimal solution must be repeated after walking path through a period of a cycle;
can prove that the path must be repeated two adjacent lattice;
\ (PRF \) :
For any period of repeated path, You are able to find the average score is not less than the average of two duplicate lattice path an entire paragraph.
\ (QED \)

Note \ (f_ {i, x, y} \) represents down \ (I \) Step arrival \ ((x, y) \ ) is the maximum value, then the link with four lattice select the highest score down $ \ frac {k - 2i} { 2} $ cycles;
\ (I \) up to \ (\ min \ {nm, \ K FRAC {2} {} \} \) .

Time complexity \ (O (n-m ^ 2 ^ 2) \) .

\(Source\)

#include <cstdio>
#include <cstring>
#include <algorithm>
int in() {
    int x = 0; char c = getchar(); bool f = 0;
    while (c < '0' || c > '9')
        f |= c == '-', c = getchar();
    while (c >= '0' && c <= '9')
        x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    return f ? -x : x;
}
template<typename T>inline void chk_min(T &_, T __) { _ = _ < __ ? _ : __; }
template<typename T>inline void chk_max(T &_, T __) { _ = _ > __ ? _ : __; }

const int N = 105;
int n, m, A, B, k;
int mp[N][N];
long long f[2][N][N], res;

void work() {
    int cur = 0, lim = std::min(n * m, k >> 1);
    memset(f[0], -1, sizeof(f[0]));
    f[0][A][B] = 0;
    for (int i = 0; i < lim; ++i, cur ^= 1) {
        memset(f[cur ^ 1], -1, sizeof(f[cur ^ 1]));
        for (int x = 1; x <= n; ++x) {
            for (int y = 1; y <= m; ++y) {
                if (!~f[cur][x][y])
                    continue;
                if (i + i < k) {
                    int max = -1;
                    chk_max(max, mp[x + 1][y]);
                    chk_max(max, mp[x - 1][y]);
                    chk_max(max, mp[x][y + 1]);
                    chk_max(max, mp[x][y - 1]);
                    chk_max(res, f[cur][x][y] + f[cur][x][y] - mp[x][y] + 1ll * (k - i - i) / 2 * (mp[x][y] + max));
                }
                if (x < n)
                    chk_max(f[cur ^ 1][x + 1][y], f[cur][x][y] + mp[x + 1][y]);
                if (x)
                    chk_max(f[cur ^ 1][x - 1][y], f[cur][x][y] + mp[x - 1][y]);
                if (y < m)
                    chk_max(f[cur ^ 1][x][y + 1], f[cur][x][y] + mp[x][y + 1]);
                if (y)
                    chk_max(f[cur ^ 1][x][y - 1], f[cur][x][y] + mp[x][y - 1]);
            }
        }
    }
    if (lim + lim <= k) {
        for (int x = 1; x <= n; ++x)
            for (int y = 1; y <= m; ++y)
                if (~f[cur][x][y])
                    chk_max(res, f[cur][x][y] + f[cur][x][y] - mp[x][y]);
    }
    printf("%lld\n", res);
}

int main() {
    //freopen("in", "r", stdin);
    freopen("maja.in", "r", stdin);
    freopen("maja.out", "w", stdout);
    n = in(), m = in(), A = in(), B = in(), k = in();
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j)
            mp[i][j] = in();
    work();
    return 0;
}

T3, djq circle of friends

\ (n \ (n \ leq 42) \) individual, numbered \ (. 1 \) ~ \ (n-\) , the relationship between points \ (0 \) two kinds, known \ (m \) group relationships ( the relationship between two people does not give twice), wondering \ (1 \) relationships with others;
suppose there is a person number \ (the X-\) ;
if \ (1 \) relationship with him is known, then the relationship between the two does not change (the relationship is bidirectional);
otherwise \ (1 \) in a certain order listed people and his relationship known;
assume that the first \ (1 \) and \ (x \) while recognizing people are \ (the y-\) , so \ (1 \) and \ (x \) relationship is \ ((1, the y-) \ xor \ (the X-, the y-) \) , which, \ ((the X-, the y- ) \) represents \ (x, y \) relationship between;
newly established relationship will not affect the determination of other people's relationships.
Seeking one individualized and\ (1 \) relationship known human sequence, such that (1 \) \ relationship \ (0 \) up number, the number of output.

\(Sol\)

Will start with (1 \) \ relationship \ (0 \) who is set to \ (A \) , and \ (1 \) do not know but (A \) \ to some people who know people in \ (B \) , obviously other people do not consider.
If \ (| A | \ Leq 20 \) , you can \ (A \) like pressure, remember \ (f_i \) represents \ (i \) of these people on the list optimal solution has emerged, a next enumeration people can occur.
Otherwise, \ (B \) like pressure, remember \ (f_i \) represents \ (i \) of these people have determined the relationship between the optimal solution, transferred above.

Time complexity \ (O (2 ^ {\ FRAC {{n-2}}} ^ n-2) \) .

\(Source\)

#include <cstdio>
#include <cstring>
#include <algorithm>
int in() {
    int x = 0; char c = getchar(); bool f = 0;
    while (c < '0' || c > '9')
        f |= c == '-', c = getchar();
    while (c >= '0' && c <= '9')
        x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    return f ? -x : x;
}
template<typename T>inline void chk_min(T &_, T __) { _ = _ < __ ? _ : __; }
template<typename T>inline void chk_max(T &_, T __) { _ = _ > __ ? _ : __; }

const int N = 51;

int n, m, cnt_a, cnt_b, tot_st, t[N][N], mp[N], id[N], f[1 << 21 | 1];
long long fri[N], agn[N];

int bit_cnt(long long x, int ret = 0) {
    for (; x; x &= (x - 1), ++ret);
    return ret;
}

namespace A {
    void work() {
        tot_st = (1 << cnt_a) - 1;
        for (int i = 2; i <= n; ++i)
            if (~t[1][i])
                id[mp[i]] = i;
        for (int i = 0; i < tot_st; ++i) {
            long long now = 0;
            for (int j = 1; j <= cnt_a; ++j)
                if (i & (1 << (j - 1)))
                    now |= (fri[id[j]] | agn[id[j]]);
            for (int j = 1; j <= cnt_a; ++j)
                if (~i & (1 << (j - 1))) {
                    if (!t[1][id[j]]) {
                        chk_max(f[i | (1 << (j - 1))], f[i] + bit_cnt(~now & fri[id[j]]));
                    } else {
                        chk_max(f[i | (1 << (j - 1))], f[i] + bit_cnt(~now & agn[id[j]]));
                    }
                }
        }
        for (int i = 1; i <= cnt_a; ++i)
            f[tot_st] += (t[1][id[i]] == 0);
        printf("%d\n", f[tot_st]);
    }
}

namespace B {
    void work() {
        tot_st = (1 << cnt_b) - 1;
        for (int i = 2; i <= n; ++i)
            if (~t[1][i])
                id[mp[i]] = i;
        for (int i = 0; i < tot_st; ++i) {
            for (int j = 1; j <= cnt_a; ++j)
                if (~i & (fri[id[j]] | agn[id[j]])) {
                    if (!t[1][id[j]]) {
                        chk_max(f[i | fri[id[j]] | agn[id[j]]], f[i] + bit_cnt(~i & fri[id[j]]));
                    } else {
                        chk_max(f[i | fri[id[j]] | agn[id[j]]], f[i] + bit_cnt(~i & agn[id[j]]));
                    }
                }
        }
        for (int i = 1; i <= cnt_a; ++i)
            f[tot_st] += (t[1][id[i]] == 0);
        printf("%d\n", f[tot_st]);
    }
}

int main() {
    //freopen("in", "r", stdin);
    freopen("friends.in", "r", stdin);
    freopen("friends.out", "w", stdout);
    n = in(), m = in();
    memset(t, -1, sizeof(t));
    for (int i = 1, x, y; i <= m; ++i) {
        x = in(), y = in();
        t[x][y] = t[y][x] = in();
    }

    for (int i = 2; i <= n; ++i) {
        if (!~t[1][i])
            continue;
        mp[i] = ++cnt_a;
        for (int j = 2; j <= n; ++j) {
            if (!~t[1][j] && ~t[i][j]) {
                if (!mp[j])
                    mp[j] = ++cnt_b;
                if (!t[i][j])
                    fri[i] |= (1ll << (mp[j] - 1));
                else
                    agn[i] |= (1ll << (mp[j] - 1));
            }
        }
    }

    if (cnt_a <= 20) {
        A::work();
    } else {
        B::work();
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/15owzLy1-yiylcy/p/11391502.html