2019 ICPC Asia Yinchuan Regional

Contest Info


Practice Link

Solved A B C D E F G H I J K L M N
9/14 O O - O - O O O O - O - - O
  • O through the game
  • Ø After the game by
  • ! I tried but failed
  • - No attempt

Solutions


A. Girls Band Party

B. So Easy

The meaning of problems:
given a \ (n \ cdot n \) rectangle, this rectangle \ (a_ {i, j} \) of the initial value \ (0 \) , each time it is possible to select a row or a plus \ (1 \) , and now cover a number of positions, so that you restore this number.

Ideas:
Consider the rewind operation, regardless of the number of cover, and then enumerate each row, each column, each row choose the minimum, the minimum row entire row to restore the entire column minus the number.

Code:


view code

#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 10;
int n, a[N][N];

int main() {
    while (scanf("%d", &n) != EOF) {
        int x = -1, y = -1;
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= n; ++j) {
                scanf("%d", &a[i][j]);
                if (a[i][j] == -1) {
                    x = i, y = j;
                    a[i][j] = 0;
                }
            }
        }
        for (int i = 1; i <= n; ++i) {
            int Min = 1e9;
            for (int j = 1; j <= n; ++j) {
                if (x == i && y == j) continue;
                Min = min(Min, a[i][j]);
            }
            for (int j = 1; j <= n; ++j) {
                a[i][j] -= Min;
            }
        }
        for (int j = 1; j <= n; ++j) {
            int Min = 1e9;
            for (int i = 1; i <= n; ++i) {
                if (x == i && y == j) continue;
                Min = min(Min, a[i][j]);
            }
            for (int i = 1; i <= n; ++i) {
                a[i][j] -= Min;
            }
        }
        printf("%d\n", -a[x][y]);
    }
    return 0;
}

D. Easy Problem

The meaning of problems:
the definition of a sequence \ ((a_1, a_2, \ cdots, a_n) \) a \ ((n, m, d ) -good \) if and only if \ (1 \ leq a_i \ leq m (1 \ leq i \ leq n) \ ) and \ (gcd (a_1, a_2,
\ cdots, a_n) = d \) order \ (F (A, K) = (a_1a_2 \ cdots A_N) ^ K \) , and now to the \ (n-, m, D, K \) , lets you find all legal \ ((n, m, d ) -good \) sequence \ (a \) a \ (f (a, k) \)

思路:
题目要求的东西等价于:
\[ \begin{eqnarray*} f(d) = \sum\limits_{a_1 = 1}^m \sum\limits_{a_2 = 1}^m \cdots \sum\limits_{a_n = 1}^m [gcd(a_1, a_2, \cdots, a_n) = d](a_1a_2\cdots a_n)^k \end{eqnarray*} \]
那么我们令:
\[ \begin{eqnarray*} g(d) = \sum\limits_{a_1 = 1}^m \sum\limits_{a_2 = 1}^m \cdots \sum\limits_{a_n = 1}^m [d | gcd(a_1, a_2, \cdots, a_n)](a_1a_2\cdots a_n)^k \end{eqnarray*} \]
显然有:
\[ \begin{eqnarray*} g(d) = (\sum\limits_{d\;|\;i} i^k)^n \end{eqnarray*} \]
莫比乌斯反演有:
\[ \begin{eqnarray*} f(d) &=& \sum\limits_{d\;|\;i} \mu(\frac{i}{d})g(i) \\ &=& \sum\limits_{d\;|\;i} \mu(\frac{i}{d}) (\sum\limits_{i\;|\;j} j^k)^n \end{eqnarray*} \]
所以:
\[ f(d) = \sum\limits_{i = 1}^{\left\lfloor m/d \right\rfloor} \mu(i) (\sum\limits_{id\;|\;j} j^k)^n \]

Code:


view code

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e5 + 10, mod = 59964251;
int pri[N], check[N], mu[N], n, m, d, K, phi; 
char s[N]; 
void sieve() {
    memset(check, 0, sizeof check);
    *pri = 0;
    mu[1] = 1;
    for (int i = 2; i < N; ++i) {
        if (check[i] == 0) {
            pri[++*pri] = i;
            mu[i] = -1;
        }
        for (int j = 1; j <= *pri; ++j) {
            if (i * pri[j] >= N) break;
            check[i * pri[j]] = 1;
            if (i % pri[j] == 0) {
                mu[i * pri[j]] = 0;
                break;
            } else {
                mu[i * pri[j]] = -mu[i];
            }
        }
    }
}

int eular(int n) {
    int ans = n;
    for (int i = 2; i * i <= n; ++i) {
        if (n % i == 0) {
            ans -= ans / i;
            while (n % i == 0) 
                n /= i;
        }
    }
    if (n > 1) ans -= ans / n;
    return ans;
}

ll gcd(ll a, ll b) {
    return b ? gcd(b, a % b) : a;
}

ll qmod(ll base, ll n) {
    ll res = 1;
    while (n) {
        if (n & 1) res = res * base % mod;
        base = base * base % mod;
        n >>= 1;
    }
    return res;
}

int getMod(int mod) {
    int res = 0;
    for (int i = 1; s[i]; ++i) {
        res = (res * 10 + s[i] - '0') % mod;
    }
    return res;
}

int main() {
    phi = eular(mod);
    sieve();    
//  cout << phi << endl;
    int _T; scanf("%d", &_T);
    while (_T--) {
        scanf("%s%d%d%d", s + 1, &m, &d, &K);
        int len = strlen(s + 1);
        if (len <= 9) {
            n = 0;
            for (int i = 1; s[i]; ++i) {
                n = n * 10 + s[i] - '0';
            }
        } else {
            n = getMod(phi);
            if (getMod(643) == 0 || getMod(93257) == 0) {
                n += phi;
            }
        }
        ll res = 0;
        for (int i = 1; i <= m / d; ++i) {
            int base = 0;
            for (int j = i * d; j <= m; j += i * d) {
                base += qmod(j, K);
                base %= mod;
            }
            res += 1ll * mu[i] * qmod(base, n) % mod;
            res = (res + mod) % mod;
        }
        printf("%lld\n", res);
    }
    return 0;
}

E. XOR Tree

The meaning of problems:
defining a weight value multiset which any two numbers and exclusive OR and the square.
Now given a rooted tree ( \ (1 \) root), the right bit for each point, defined \ (p (x, k) \) of \ (X \) subtree distance \ (X \) not more than \ (K \) weights multiset all points constituting the right points, it is now for each \ (i \ in [1, n] \) seeking \ (p (i, k) \)

F. Function!

G. can !!

Bare tree line.

Code:


view code

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int n, q;
struct SEG {
    struct node {
        int Max, lazy;
        node() { Max = lazy = 0; }
        void up(int x) {
            Max += x;
            lazy += x;
        }
        node operator + (const node &other) const {
            node res = node();
            res.Max = max(Max, other.Max);
            return res;
        }
    }t[N << 2];
    void build(int id, int l, int r) {
        t[id] = node();
        if (l == r) return;
        int mid = (l + r) >> 1;
        build(id << 1, l, mid);
        build(id << 1 | 1, mid + 1, r);
    }
    void down(int id) {
        int &lazy = t[id].lazy;
        if (lazy) {
            t[id << 1].up(lazy);
            t[id << 1 | 1].up(lazy);
            lazy = 0;
        }
    }
    void update(int id, int l, int r, int ql, int qr, int v) {
        if (l >= ql && r <= qr) {
            t[id].up(v);
            return;
        }
        int mid = (l + r) >> 1;
        down(id);
        if (ql <= mid) update(id << 1, l, mid, ql, qr, v);
        if (qr > mid) update(id << 1 | 1, mid + 1, r, ql, qr, v);
        t[id] = t[id << 1] + t[id << 1 | 1];
    }
    int query(int id, int l, int r, int ql, int qr) {
        if (l >= ql && r <= qr) return t[id].Max;
        int mid = (l + r) >> 1;
        down(id);
        int res = 0;
        if (ql <= mid) res = max(res, query(id << 1, l, mid, ql, qr));
        if (qr > mid) res = max(res, query(id << 1 | 1, mid + 1, r, ql, qr));
        return res;
    }
}seg[4];

int main() {
    int id[] = {0, 0, 0, 1, 0, 2, 0, 3, 0};
    vector <vector<int>> vec;
    vec.resize(15);
    for (int i = 2; i <= 10; ++i) {
        int x = i;
        vec[i].clear();
        for (int j = 2; j <= x; ++j) {
            while (x % j == 0) {
                vec[i].push_back(j);
                x /= j;
            }
        }
    //  cout << i << endl;
    //  for (auto &it : vec[i])
    //      cout << it << " ";
    //  cout << endl;
    }
    while (scanf("%d%d", &n, &q) != EOF) {
        for (int i = 0; i < 4; ++i) seg[i].build(1, 1, n);
        char op[20]; int l, r, x;
        while (q--) {
            scanf("%s%d%d", op, &l, &r);
            if (op[1] == 'U') {
                scanf("%d", &x);
                for (auto &it : vec[x]) {
                    seg[id[it]].update(1, 1, n, l, r, 1);
                }
            } else {
                int res = 0;
                for (int i = 0; i < 4; ++i) {
                    res = max(res, seg[i].query(1, 1, n, l, r));
                }
                printf("ANSWER %d\n", res);
            }
        }   
    }
    return 0;
}

H. Delivery Route

Meaning of the questions:
given a graph, \ (x \) Article undirected edges, there \ (y \) strip directed edges, to ensure that no weights are positive side, there may be a negative side to the right value, and If there is a guarantee to the edge \ (a_i \ rightarrow b_i \) , then in this figure, \ (b_i \) can not reach \ (a_i \)
are now asking from \ (s \) departure to any point of the shortest.

Ideas:
we have to consider if you only consider the edge, then a \ (DAG \) , then each block the no Unicom together into the side as a new point, and has directed edges connect them together, they are also a \ (DAG \) .
No negative side and no right, to the inside can run dijkstra block diagram of the communication, and then click to the topology dp sequence.

Code:


view code

#include <bits/stdc++.h>
using namespace std;
using pII = pair<int, int>;
#define dbg(x...) do { cout << "\033[32;1m" << #x << " -> "; err(x); } while (0)
void err() { cout << "\033[39;0m" << endl; }
template <class T, class... Ts>
void err(const T& arg, const Ts&... args) { cout << arg << ' '; err(args...); }
#define fi first
#define se second
const int N = 5e4 + 10, INF = 0x3f3f3f3f;
int n, mx, my, s, id[N], d[N];
//0 two-way 1 one-way
vector <vector<pII>> G[3];
vector <vector<int>> po;
struct DSU {
    int fa[N];
    void init() { memset(fa, 0, sizeof fa); }
    int find(int x) {
        return fa[x] == 0 ? x : fa[x] = find(fa[x]);
    }
    void merge(int u, int v) {
        int fu = find(u), fv = find(v);
        if (fu != fv) {
            fa[fu] = fv;
        }
    }
}dsu;

struct node {
    int u, w;
    node() {}
    node(int u, int w) : u(u), w(w) {}
    bool operator < (const node &other) const {
        return w > other.w;
    }
};
int dis[N], used[N];
void Dijkstra(int S) {
    priority_queue <node> pq;
    pq.push(node(S, dis[S]));
    while (!pq.empty()) {
        int u = pq.top().u; pq.pop();
        for (auto &it : G[0][u]) { 
            int v = it.fi, w = it.se;
            if (dis[v] > dis[u] + w) {
                dis[v] = dis[u] + w;
                pq.push(node(v, dis[v]));
            }   
        }
    }
}

void Topo() {
    queue <int> que;
    for (int i = 1; i <= *id; ++i) {
        if (d[i] == 0) {
            que.push(i);
        }
    }   
    while (!que.empty()) {
        int u = que.front(); que.pop();
        sort(po[u].begin(), po[u].end(), [&](int a, int b) { return dis[a] < dis[b]; });
        for (auto &it : po[u]) {
            Dijkstra(it);
            for (auto &it2 : G[1][it]) {
                int v = it2.fi, w = it2.se;
                if (dis[it] < INF) {
                    dis[v] = min(dis[v], dis[it] + w);
                }
            }
        }   
        for (auto &it : G[2][u]) {
            int v = it.fi;
            if (--d[v] == 0) {
                que.push(v);
            }
        }
    }
}

int main() {
    while (scanf("%d%d%d%d", &n, &mx, &my, &s) != EOF) {
        for (int i = 1; i <= n; ++i) {
            dis[i] = INF;
        }
        dis[s] = 0;
        *id = 0;
        G[0].clear(); G[1].clear();
        G[0].resize(n + 1); G[1].resize(n + 1);
        for (int i = 1, u, v, w; i <= mx; ++i) {
            scanf("%d%d%d", &u, &v, &w);
            G[0][u].push_back(pII(v, w));
            G[0][v].push_back(pII(u, w));
        }
        for (int i = 1, u, v, w; i <= my; ++i) {
            scanf("%d%d%d", &u, &v, &w);
            G[1][u].push_back(pII(v, w));
        }
        dsu.init();
        for (int u = 1; u <= n; ++u) {
            for (auto &it : G[0][u]) {
                int v = it.fi;
                dsu.merge(u, v);
            }
        }
        for (int u = 1; u <= n; ++u) {
            if (dsu.fa[u] == 0)
                id[u] = ++*id;
        }
        for (int u = 1; u <= n; ++u) {
            if (dsu.fa[u]) {
                id[u] = id[dsu.find(u)];
            }
        }
    //  for (int i = 1; i <= n; ++i)
    //      dbg(i, id[i]); 
        po.clear(); po.resize(*id + 10);
        G[2].clear(); G[2].resize(*id + 10);
        memset(d, 0, sizeof d);
        for (int u = 1; u <= n; ++u) {
            po[id[u]].push_back(u); 
            for (auto &it : G[1][u]) { 
                int v = it.fi;
                if (id[u] != id[v]) {
                    G[2][id[u]].push_back(pII(id[v], v));
                    ++d[id[v]];
                }
            }
        }
        Topo();
        for (int i = 1; i <= n; ++i) {
            if (dis[i] >= INF) puts("NO PATH");
            else printf("%d\n", dis[i]);
        }
        
    }
    return 0;
}

I. Base62

Meaning of the questions:
hex conversion

Code:


view code


def main():
    l = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
         'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
         'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
    x, y, z = input().split()
    x = int(x)
    y = int(y)
    num = 0
    for c in z:
        if ord('0') <= ord(c) <= ord('9'):
            num = num * x + ord(c) - ord('0')
        elif ord('A') <= ord(c) <= ord('Z'):
            num = num * x + ord(c) - ord('A') + 10
        else:
            num = num * x + ord(c) - ord('a') + 36
    if num == 0:
        print("0")
        return 
    res = ""
    while num > 0:
        tmp = num % y
        res = res + l[tmp]
        num = num // y
    # print(res)
    res = res[::-1]
    print(res)

main()

K. Largest Common Submatrix

The meaning of problems:
given two (n \ cdot m \) \ rectangle, and the number of which is the \ ([1, nm] \ ) is arranged.
The maximum common sub-rectangle sum of two rectangles, defined here as a large area.

Thinking:
Number inside a consideration is arranged to be \ (O (n ^ 2) \) process to expand the number of how much each of the upward expansion of the number to the left, then consider each line, it must be a certain length and then multiplied by a continuous this minimum amount of upward expansion.
Upward expansion as a part of this dimension, as a one-dimensional position, thrown into a Cartesian tree run inside each of the minimum run can run out of the scope of the jurisdiction, then the left and right extended range intersection, that is, each number expand upward It can be extended laterally farthest range.

Code:


view code

#include <bits/stdc++.h>
using namespace std;
using pII = pair<int, int>; 
#define dbg(x...) do { cout << "\033[32;1m" << #x << " -> "; err(x); } while (0)
void err() { cout << "\033[39;0m" << endl; }
template <class T, class... Ts>
void err(const T& arg, const Ts&... args) { cout << arg << ' '; err(args...); }
#define fi first
#define se second
const int N = 1e3 + 10, INF = 0x3f3f3f3f;
int n, m, a[N][N], b[N][N], l[N][N], r[N][N], num[N][N];
pII c[N], id[N * N];

struct CT {
    struct node {
        int id, val, fa;
        int son[2];
        node() {}
        node (int id, int val, int fa) : id(id), val(val), fa(fa) {
            son[0] = son[1] = 0;
        }
        bool operator < (const node &other) const {
            return val < other.val;
        }
    }t[N];
    int root;
    void init() {
        t[0] = node(0, -INF, 0);
    }
    void build(int n, int *a) {
        for (int i = 1; i <= n; ++i) {
            t[i] = node(i, a[i], 0);
        }
        for (int i = 1; i <= n; ++i) {
            int k = i - 1;
            while (t[i] < t[k]) {
                k = t[k].fa;
            }
            t[i].son[0] = t[k].son[1];
            t[k].son[1] = i;
            t[i].fa = k;
            t[t[i].son[0]].fa = i;
        }
        root = t[0].son[1];
    }
    int dfs(int u) {
        if (!u) return 0;
        c[u].fi = dfs(t[u].son[0]);
        c[u].se = dfs(t[u].son[1]);
        return c[u].fi + c[u].se + 1;
    }
}ct;

int main() {
    while (scanf("%d%d", &n, &m) != EOF) {
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= m; ++j) {
                scanf("%d", &a[i][j]);
            }
        }
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= m; ++j) {
                scanf("%d", &b[i][j]);
                id[b[i][j]] = pII(i, j); 
            }
        }

        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= m; ++j) {
                if (j == 1) {
                    l[i][j] = j;
                } else {
                    int pre = a[i][j - 1], now = a[i][j];
                    if (id[pre].fi == id[now].fi && id[pre].se == id[now].se - 1) {
                        l[i][j] = l[i][j - 1];
                    } else {
                        l[i][j] = j;
                    }
                }
            }
            for (int j = m; j >= 1; --j) {
                if (j == m) {
                    r[i][j] = j;
                } else {
                    int nx = a[i][j + 1], now = a[i][j];
                    if (id[nx].fi == id[now].fi && id[nx].se == id[now].se + 1) {
                        r[i][j] = r[i][j + 1];
                    } else {
                        r[i][j] = j;
                    }
                }
            }
        }
        for (int j = 1; j <= m; ++j) {
            for (int i = 1; i <= n; ++i) {
                if (i == 1) {
                    num[i][j] = 1;
                } else {
                    int pre = a[i - 1][j], now = a[i][j];
                    if (id[pre].fi == id[now].fi - 1 && id[pre].se == id[now].se) {
                        num[i][j] = num[i - 1][j] + 1;
                    } else {
                        num[i][j] = 1;
                    }
                }
            }
        }
        int res = 0;
        for (int i = 1; i <= n; ++i) {
        //  for (int j = 1; j <= m; ++j) {
        //      dbg(i, j, l[i][j], r[i][j], num[i][j]);
        //  }
            ct.init();
            ct.build(n, num[i]);
            ct.dfs(ct.root);
            for (int j = 1; j <= m; ++j) {
                int tl = max(l[i][j], j - c[j].fi);
                int tr = min(r[i][j], j + c[j].se);
                res = max(res, (tr - tl + 1) * num[i][j]);
            }
        }
        printf("%d\n", res);
    }
    return 0;
}

N. Fibonacci Sequence

Pure title output

Guess you like

Origin www.cnblogs.com/Dup4/p/11963769.html