AtCoder Beginner Contest 010

A

Problem

Given a string \(S\) , output a new string with S append "pp" .

Solutions

So just use \(std::string\) in \(C++\) .

    std::string s; std::cin >> s; s += "pp";
    std::cout << s << "\n";

B

Problem

There are \(n\) flowers with petals of \(a_1, a_2, a_3, \cdots, a_n\) respectively in your garden.
There are two ways to count petals in a loop :

  • A cycle is "like, disgusting" .
  • A cycle is "like, disgusting, like very much" .

Your girlfriend will choose any flower in your garden and use any counting method to determine your attitude towards her.
You knew about this in advance and planned to remove some petals so that the result she would get would definitely be "like" or "like ver much" .
How many petals do you need to remove at least?

Solutions

We just need to remove the minimum number of petals so that \(\forall i, \left ( a_i \equiv 1 (\bmod 2) \right ) \wedge ( a_i \equiv 1 \vee 0 (\bmod 3) )\) .

More specifically, \(a_i\) is legal if one of the floowing conditions it satisfied :

  • \[ \begin{cases} a_i \equiv 1 (\bmod 2) \\ a_i \equiv 1 (\bmod 3) \\ \end{cases} \Rightarrow a_i \equiv 1 + 2 \times 3 (\bmod [2, 3]) \Rightarrow a_i \equiv 1 (\bmod 6) \]

  • \[ \begin{cases} a_i \equiv 1 (\bmod 2) \\ a_i \equiv 0 (\bmod 3) \\ \end{cases} \Rightarrow a_i \equiv 1 + 2 \times 1 (\bmod [2, 3]) \Rightarrow a_i \equiv 3 (\bmod 6) \]

So \(a_i\) just satisfied \(a_i \equiv 1 (\bmod 6)\) or \(a_i \equiv 3 (\bmod 6)\) .

Owing to the continuous \(6\) numbers forming a complete residual system of module \(n\) , each flower can pick up to \(6\) petals at most. So we can just use brute algorithm of time complextiy is \(T(6 n) = O(n)\) .

The pseudo code is like this :

c <- 0
for i = 1 to n
  while (a[i] % 6 != 1 && a[i] % 6 != 3 && a[i] >= 0) // or while (a[i] % 2 != 1 && (a[i] % 3 != 1 || a[i] % 3 != 0) && (a[i] >= 0))
    a[i]--
    c++
print(c)

However we can use a algorithm of time is \(T(n)\) by calculate the maximum \(v_1\) and \(v_2\) so that \(1 + 6 \times t_1 = v_1 \leq a_i\) and \(3 + 6 \times t_2 = v_2 \leq a_i\) , So the maximum number legal number is \(p = max( \lfloor \frac{a_i - 1}{6} \rfloor 6 + 1, \lfloor \frac{a_i - 3}{6} \rfloor 6 + 3 )\) . Also we knew \(0\) is legal in this number, but \(p\) is need be a non negative integer in this context, so \(p = max\{ 0, \lfloor \frac{a_i - 1}{6} \rfloor 6 + 1, \lfloor \frac{a_i - 3}{6} \rfloor 6 + 3 \}\) .

Due to the possibility of nagative numbers during the calclation process, we need to rewrite the division.

The code is :

i64 floordiv(i64 a, i64 b) {
    if (a % b == 0) return a / b;
    else if ((a ^ b) > 0) return a / b;
    else return a / b - 1;
}
i64 ceildiv(i64 a, i64 b) {
    if (a % b == 0) return a / b;
    else if ((a ^ b) > 0) return a / b + 1;
    else return a / b;
}
void solve() {
    int n; std::cin >> n;
    int c = 0;
    for (int i = 1; i <= n; i++) {
        int x; std::cin >> x;
        int p = std::max<i64>({0LL,
            floordiv(x - 1, 6) * 6 + 1, floordiv(x - 3, 6) * 6 + 3});
        c += x - p;
    }
    std::cout << c << "\n";
}

How do we calculate the following congruence equation class?

\[\begin{cases} X \equiv a (\bmod b) \\ X \equiv c (\bmod d) \\ \end{cases} \]

\[\begin{aligned} X &= a + bx = c + dy \\ &\Rightarrow bx - dy = c - a \\ &\Rightarrow x = x_0 + \frac{d}{(b, d)} t \\ &\Rightarrow X = a + bx = a + b x_0 + b \frac{d}{(b, d)} t = a + b x_0 + [b, d] t \\ &\Rightarrow X \equiv a + b x_0 (\bmod [b, d]) \\ \end{aligned} \]

Owing to we just calculate linear congruence equation \(ax + by = p\) , the time complexity is \(O(\log M)\) whicle \(M\) is range of numbers.

If we need calculate the following congruence equation class

\[\begin{cases} X \equiv p_1 (\bmod q_1) \\ X \equiv p_2 (\bmod q_2) \\ \cdots \\ X \equiv p_n (\bmod q_n) \\ \end{cases} \]

we can just union the congruence eqution class of size \(2\) with time complexity of \(O(n \log M)\) .


How do we calculate the linear congruence?

\[ax + by = p \]

First at all, if we can calculate a set of minimum solution \((x_0, y_0)\) , the general solution is \((x_0 + \frac{b}{(a, b)} t, y_0 - \frac{a}{(a, b)} t)\) .

So how do we calclete it's minmum solution? It is equivalent to \(\frac{a}{(a, b)} x + \frac{b}{(a, b)} y = \frac{p}{(a, b)}\) , and according to the Bézout's lemma iff \((a, b) \mid p\) the equation with a solution.
So we can rewrite it is \(a^{'} x + b^{'} y = p^{'}\) after divide the equation left and right by \((a, b)\) .
We can calculate the minimu solution of \(a^{'} x + b^{'} y = 1\) by using Euclid algorithm so we rewrite it as \(a^{'} x^{'} + b^{'} y^{'} = 1\) . Then we can calculate a solution \(x^{'}_0\) , so \(x_0 = x^{'}_0 \times p^{'} \bmod b^{'}\) and \(y^{0}\) can be directly calculated as \(\frac{p^{'} - a^{'} x_0}{b^{'}}\) .


How do we calculate the minimu solution (positive) of the linear congruence by using Euclid algorithm?

\[ax + by = 1 \ s.t. (a, b) = 1 \]

We just rewrite it as

\[\begin{aligned} (\lfloor \frac{a}{b} \rfloor b + a \bmod b) x + by &= 1 \\ \rightarrow b ( \lfloor \frac{a}{b} \rfloor x + y) + (a \bmod b) x &= 1 \\ \end{aligned} \]

and let

\[\begin{cases} a^{'} = b \\ b^{'} = a \bmod b \\ x^{'} = \lfloor \frac{a}{b} \rfloor x + y \\ y^{'} = x \end{cases} \]

Then we get

\[f(a, b) \rightarrow f(b, a \bmod b) = f(a^{'}, b^{'}) \]

Because \((a, b) = (a, a \bmod b) = 1\) , recursion will end at \(a^{'} = 1, b^{'} = 0\) , then we construction \(x^{'} = 1, y^{'} = 0\) . So we got a minimum solution of the recursion.

For the calculate of \(x, y\) :

\[\begin{aligned} y^{'} = x &\Rightarrow x = y^{'} \\ x^{'} = \lfloor \frac{a}{b} \rfloor x + y &\Rightarrow y = x^{'} - \lfloor \frac{a}{b} \rfloor y^{'} \\ \end{aligned} \]

For the solution of calculate the positive minimu solution of \(ax + by = 1 \ s.t. (a, b) = 1\) by using Eucild algorithm, we can sure that :

  • The solution is must be the positive minimum solution.
  • \(x \leq b, y \leq a\) forever.

But i can't explain it in detail. Fortunately, they are quite obvious.

C

Problem

In Cartesian coordinate system, give a strating point \((sx, sy)\) and an edning point \(tx, ty\) . You have \(T\) minutes of time and can move \(V\) units per minute.
There are \(n\) points \((x_1, y_1), (x_2, y_2), (x_3, y_3), \cdots, (x_n, y_n)\) .
Can you reach the endpoint from the strating point within the specified time with passing through one of the points?

Solutions

The first solution is that we can just traverse the \(n\) opint and check if \(distance((sx, sy), (x_i, y_i)) + distance((x_i, y_i), (tx, ty)) \leq T \times V\) . The time complexity is \(O(n)\) .

We shoule check if \(val = \sqrt{(sx - x_i)^{2} + (sy - y_i)^{2}} + \sqrt{(tx - x_i)^{2} + (ty - y_i)^{2}} \leq T \times V\) . Because floating point numbers have precision errors, we should use neighborhood.

  • \(a = b \Leftrightarrow -\varepsilon < a - b < \varepsilon\) .
  • \(a > b \Leftrightarrow a - b \geq \varepsilon\) .
  • \(a < b \Leftrightarrow a - b \leq -\varepsilon\) .

So if we want to check if \(val \leq T \times V\) we shoule check if \(val - T \times V < \varepsilon\) .

view
int Distance2(int x1, int y1, int x2, int y2) {
    return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
};
void solve() {
    int sx, sy, tx, ty; std ::cin >> sx >> sy >> tx >> ty;
    int T, V; std::cin >> T >> V;
    int n; std::cin >> n;
    int ok = 0;
    for (int i = 1; i <= n; i++) {
        int x, y; std::cin >> x >> y;
        double p = (std::sqrt(Distance2(sx, sy, x, y)) + std::sqrt(Distance2(x, y, tx, ty))) - T * V;
        if (p < EPS)
            ok = 1;
    }
    std::cout << (ok ? "YES" : "NO") << "\n";
}

Of course we can obtain an ellipse such that \(|\vec{c_1 p}| + |\vec{c_2 p}| = V \times T\) . We can just check if there are any points inside or on the ellipse.

If the given ellipse is simple as \(\frac{(x - x_0)^{2}}{a^{2}} + \frac{(y - y_0)^{2}}{a^{2} - c^{2}} = 1\) we can just check if \((x_i - x_0)^{2} \left ( 4 a^{2} - (2c)^{2} \right ) + 4(y_i - y_0)^{2} a^{2} \leq a^{2} \left( 4 a^{2} - (2c)^{2} \right)\) to avoid floating point numbers.

If the given ellipse is general, there may be have a solution to avoid floating point numbers but it will be more troublesome.

D

Problem

Given a simple connectivity undirected graph whit \(n\) points and \(m\) edges to represent your social network at work. Each point represent a preson and point \(0\) represents you. If there is an edge between two points, it meads they are friends.

If you meet someone, then you can also meet their firend. Obviously, you meet your friend. More specifically, if two points are connected, it means they meet each other. You can talk to anyone you meet.

Your girlfriend, who isn't on your social network at work. Don't want to you talk wiht any girl at work. In one operation, she can choose one of the following two operations.

  • Cut off the friendship between two people.
  • Forbid one person talk with you but you can still meet theitr friends through them.

What is the minimum numbers of operations your girl friend can execute so that you can't talk with any girl at work?

\(1 \leq n \leq 100, 1 \leq m \leq \frac{n(n + 1)}{2}\)

Solutions

Maxmum flow Minimun Cut theory

S-T Cut

Given a graph \(G(V, E)\) , a soure point \(s\), a sink point \(t\) .

Split point set \(V\) into two subset \(S, T\) .

  • \(s \in S, t \in T\)
  • \(S \cap T = \emptyset, S \cup T = V\)
    The pair \((S, T)\) is called S - T Cut.

\(Capacity(S, T)\) = sum of weights of the edges leaving \(S\) .

Note that :

  • S-T Cut is not unique.
  • \(\forall e \in E, (e \in S) \vee (e \in T) \vee (e \ \textbf{through} \ S \ \textbf{and} \ T)\)
Min-Cut

Min-Cut is the S-T Cut which \(Capacity(S, T)\) is miminmum. It is satisfied all the properties of S-T Cut also.

In a simple undirected postive weight graph, Min-Cut is Max-Flow.

But I don't have the ability and time to prove it as an undergraduate becasue it's a classic and complex algorithm. However, it's so classic that everyone konws it, so you can not help but know.

For Max-Flow, the length is too long, so it will be skipped temporarily.


We just need to consider point \(0\) as the source point \(s\) , let the edge weight of the graph be \(1\). And we would better change the edge on the source point to the exit edge.

Establish a sink point \(t\) , And connect all girl nodes with a directed edge with weight is \(1\) to \(t\) . Then the answer is the minimum cut of the graph.

The solution is obvious if it is proposed.

  • \(\forall p \in \{ \textbf{girl point} \}, e(p,t) \in T \vee e(p, t) \textbf{through} \ S, T\) .
    • If \(e(p, t) \in T\), it is obvious that \(p\) can not reach \(s\) if we delet \(e(p, t)\) .
    • If \(e(p, t) \textbf{through} \ S, T\) , we can just delet the starting point \(p\) of \(e(p, t)\) .

We can use Dinic which time complexity is \(O(n^{2}m) = O(n^{4})\) .

  • Be careful the template of Dinic uses points starting from \(1\), so we should change \(s\) from \(0\) to \(N + 1\) . And we can establish \(t\) as \(N + 2\) .

  • Be careful the FlowGraph should be establish in global domain and initialized in solve function domain because of the memory.

Dinic
// ~~ SEG STARST
template<typename T, const int V = 1010, const int E = 101000>
struct FlowGraph {
    int s, t, vtot;
    int head[V], etot;
    int dist[V], cur[V];
    
    FlowGraph(){}
    FlowGraph(int _s, int _t, int _vtot) {
        init(_s, _t, _vtot);
    }

    void init(int _s, int _t, int _vtot) {
        s = _s;
        t = _t;
        vtot = _vtot;
        for (int i = 1; i <= vtot; i++) head[i] = -1;
    }
    
    struct edge {
        int v, nxt;
        T f;
    } e[E * 2];
    
    void addedge(int u, int v, T f1, T f2 = 0) {
        e[etot] = {v, head[u], f1}; head[u] = etot++;
        e[etot] = {u, head[v], f2}; head[v] = etot++;
    }

    bool bfs() {
        for (int i = 1; i <= vtot; i++) {
            dist[i] = 0;
            cur[i] = head[i];
        }
        std::queue<int> q;
        q.push(s); dist[s] = 1;
        while (!q.empty()) {
            int u = q.front(); q.pop();
            for (int i = head[u]; ~i; i = e[i].nxt) {
                if (e[i].f && !dist[e[i].v]) {
                    int v = e[i].v;
                    dist[v] = dist[u] + 1;
                    if (v == t) return true;                                                                      
                    q.push(v);
                }
            }
        }
        return false;
    }

    T dfs(int u, T m) {
        if (u == t) return m;
        T flow = 0;
        for (int i = cur[u]; ~i; cur[u] = i = e[i].nxt) {
            if (e[i].f && dist[e[i].v] == dist[u] + 1) {
                int v = e[i].v;
                T f = dfs(v, std::min(m, e[i].f));
                e[i].f -= f;
                e[i ^ 1].f += f;
                m -= f;
                flow += f;
                if (!m) break;
            }
        }
        if (!flow) dist[u] = -1;
        return flow;
    }

    T dinic() {
        T flow = 0;
        while (bfs()) flow += dfs(s, std::numeric_limits<T>::max());
        return flow;
    }
};
// ~~ SEG END
FlowGraph<int> g;
solve
void solve() {
    int N, G, E; std::cin >> N >> G >> E;
    int s = N + 1, t = N + 2;
    g.init(s, t, N + 2);
    for (int i = 1; i <= G; i++) {
        int x; std::cin >> x;
        g.addedge(x, t, 1);
    }
    for (int i = 1; i <= E; i++) {
        int u, v; std::cin >> u >> v;
        if (u > v) std::swap(u, v);
        if (u == 0) g.addedge(s, v, 1, 1);
        else g.addedge(u, v, 1, 1);
    }
    int ans = g.dinic();
    std::cout << ans << "\n";
}

Pro problem

problem1

If we can only delete edges.

solution
We may need to shrink all girl points into one point before using Min-Cut.

problem2

If we need to incur costs when deleting points and edges.

solution
We need to split each points into two and assign edge weights before using Min-Cut.

posted @ 2024-08-14 20:46  03Goose  阅读(37)  评论(0)    收藏  举报