Arranging Cows

**Time limit:** 2 seconds    **Memory limit:** 256 megabytes

## Description

You are given a length-$N$ bitstring $s_{1\ldots N}$ ($2\le N\le 10^9$). In one operation, you can reverse a range $s_{l\ldots r}$ if the following conditions are true:

- The size of the range is even.
- The first half of the range consists of one character (either $0$ or $1$), and the second half contains the opposite character.
- Either $l=1$ or $s_{l-1}\ne s_l$.
- Either $r=N$ or $s_{r+1}\ne s_r$.

Find the minimum number of operations to move all of the $1$s to the front, or report that it is impossible. If it is possible to do so, also output the number of sequences of operations achieving this minimum, modulo $10^9+7$.

## Input Format

The first line contains $T$ ($1\le T\le 2026$), the number of independent tests. Each test is specified in the following format:

The bitstring is given in a compressed format. The first line contains $R$, the number of runs in the string ($2\le R\le 800$), and the first character of the string (either `0` or `1`).

The next line contains $R$ space-separated integers $l_1, l_2, l_3, \ldots, l_R$ ($0 < l_i < 10^9$), the lengths of maximal consecutive blocks of equal characters in $s$. It is guaranteed that $N = \sum_{i=1}^{R} l_i \le 10^9$.

Additionally, it is guaranteed that the sum of $R^2$ over all tests does not exceed $1.5 \cdot 10^6$.

## Output Format

For each test case, print the minimum number of operations to move all of the $1$s to the front or $-1$ if it is impossible, as well as the number of sequences of operations achieving this minimum modulo $10^9+7$.

## Examples

**Input 1**

```
9
2 0
1 1
2 1
1 1
2 1
2 1
2 0
1 2
5 0
1 1 1 2 1
3 0
1 2 1
8 0
1 1 2 1 1 2 1 1
6 0
3 3 1 2 2 1
7 0
5 1 1 3 2 1 1
```

**Output 1**

```
1 1
0 1
0 1
-1 0
2 1
-1 0
4 7
3 1
4 1
```

Here is the sequence of two operations for the fifth testcase: $010110 \to 100110 \to 111000$.

**Input 2**

```
5
2 1
1 1
4 1
1 1 1 1
6 1
1 1 1 1 1 1
8 1
1 1 1 1 1 1 1 1
10 1
1 1 1 1 1 1 1 1 1 1
```

**Output 2**

```
0 1
1 1
2 1
3 3
4 9
```

In all of these test cases, the minimum number of operations equals $R/2-1$.

Here are all three possible sequences of three operations for the fourth test case:

```
(1)
   10101010
-> 11001010
-> 11001100
-> 11110000

(2)
   10101010
-> 10110010
-> 10001110
-> 11110000

(3)
   10101010
-> 10101100
-> 11001100
-> 11110000
```

## Scoring

- Input 3: $N\le 10$, all tests are distinct.
- Input 4: $R\le 10$.
- Inputs 5-8: $R\le 100$, the sum of $R^2$ over all tests does not exceed $10^5$, the minimum number of operations is guaranteed to equal $R/2-1$.
- Inputs 9-12: $R\le 100$, the sum of $R^2$ over all tests does not exceed $10^5$.
- Inputs 13-16: No additional constraints.

**Problem credits:** Sujay Konda

#include "testlib.h"
int main(int argc, char *argv[]) {
    registerValidation(argc, argv);
    int T = inf.readInt(1, 2026, "T"); inf.readEoln();
    long long sumR2 = 0;
    for (int tc = 1; tc <= T; tc++) {
        int R = inf.readInt(2, 800, "R"); inf.readSpace();
        int first = inf.readInt(0, 1, "first_char"); inf.readEoln();
        (void)first;
        sumR2 += (long long)R * R;
        long long N = 0;
        for (int i = 1; i <= R; i++) {
            int l = inf.readInt(1, 999999999, "l_i");  // 0 < l_i < 1e9
            N += l;
            if (i < R) inf.readSpace();
        }
        inf.readEoln();
        ensuref(N <= 1000000000LL, "test %d: N=%lld > 1e9", tc, N);
    }
    ensuref(sumR2 <= 1500000LL, "sum R^2 %lld > 1.5e6", sumR2);
    inf.readEof(); return 0;
}

#include <bits/stdc++.h>
using namespace std;

const int LGN = 30;
const int INF = 1e9;
const int MOD = 1e9 + 7;
using ll = long long;

const int MXM = 1000;

int f[MXM + 1], invf[MXM + 1];

int mulm(int x, int y) {
    return (ll)x * y % MOD;
}

int bpow(int x, int y) {
    return (y == 0 ? 1 : mulm(bpow(mulm(x, x), y / 2), (y % 2 ? x : 1)));
}

int choose(int n, int k) {
    if(k > n) return 0;
    if(k < 0) return 0;
    assert(n >= 0);
    return mulm(mulm(f[n], invf[k]), invf[n - k]);
}

void tc() {
    int M; cin >> M; char c; cin >> c;
    vector<int> a;
    for(int i = 0; i < LGN; i++)
        a.push_back(0);
    for(int i = 0; i < M; i++) {
        int ai; cin >> ai;
        a.push_back(ai);
    }
    for(int i = 0; i < LGN; i++)
        a.push_back(0);

    vector<int> p(M + 2 * LGN);
    for(int i = 2; i < M + 2 * LGN; i++) {
        p[i] = a[i] + p[i - 2];
    }

    vector<vector<bool>> dp(M + 2 * LGN, vector<bool>(M + 2 * LGN));
    vector<vector<int>> dp2(M + 2 * LGN, vector<int>(M + 2 * LGN));

    map<int, vector<pair<int, int>>> trans;

    // add possible transitions from l, r
    auto add_trans = [&] (int l, int r) {
        if(r < LGN || l >= M + LGN) return;

        trans[p[r - 1] + p[l - 1]].push_back({l, r});
    };

    for(int i = 0; i < M + 2 * LGN - 1; i++) {
        dp[i][i + 1] = true;
        dp2[i][i + 1] = 1;
        add_trans(i, i + 1);
    }

    for(int sz = 4; sz <= M + 2 * LGN; sz += 2) {
        for(int l = 1; l + sz - 1 < M + 2 * LGN; l++) {
            int r = l + sz - 1;
            for(auto [u, v] : trans[p[r - 1] + p[l - 1]]) {
               if(l < u && v < r && dp[l][u] && dp[v][r]) {
                    dp[l][r] = true;
                    int ways = mulm(f[(r - l) / 2 - 1], mulm(invf[(r - v) / 2], mulm(invf[(v - u) / 2], invf[(u - l) / 2])));
                    dp2[l][r] += mulm(ways, mulm(dp2[u][v], mulm(dp2[l][u], dp2[v][r])));
                    dp2[l][r] %= MOD;
                }
            }
            if(dp[l][r])
                add_trans(l, r);
        }
    }
    int ans = INF;
    int ans2 = 0;
    for(int l = 0; l <= LGN; l++) {
        for(int r = M + LGN - 1; r < M + 2 * LGN; r++) {
            if(dp[l][r] && (LGN - l) % 2 == (c == '0')) {
                if ((r - l) / 2 < ans) {
                    ans = (r - l) / 2;
                    ans2 = 0;
                }
                if((r - l) / 2 == ans) {
                    ans2 += dp2[l][r];
                    ans2 %= MOD;
                }
            }
        }
    }
    cout << ((ans == INF) ? -1 : ans) << " ";
    cout << ans2 << endl;
}

int main() {

    f[0] = 1;
    for(int i = 1; i <= MXM; i++) {
        f[i] = mulm(f[i - 1], i);
    }
    invf[MXM] = bpow(f[MXM], MOD - 2);
    for(int i = MXM; i >= 1; i--) {
        invf[i - 1] = mulm(invf[i], i);
    }

    ios::sync_with_stdio(false), cin.tie(nullptr);
    int T; cin >> T;
    while(T--) tc();
}

verbatim earliest root score=100 submission #169142


Haybale Stacks

**Time limit:** 2.5 seconds    **Memory limit:** 256 megabytes

## Description

Farmer John has $N$ stacks of haybales ($1\le N\le 5\cdot 10^5$), where the $i$-th stack contains $a_i$ haybales ($1\le a_i\le 10^9$). He wants to remove all of these haybales and has $M$ ($1\le M\le 2500$) cows available to help him. If hired, the $i$-th cow will repeat the following $s_i$ times ($1\le s_i\le 100$) for a cost of $c_i$ ($1\le c_i\le 10^9$):

- If the stack contains at least $p_i$ haybales ($1\le p_i\le 10^9$), then the cow will remove one haybale.
- If the stack contains less than $p_i$ haybales, the cow does nothing.

For each stack, FJ wants to remove all of the haybales in it. He will do this by hiring cows in sequence (possibly the same cow more than once) until the stack becomes empty. Help FJ determine for each stack the minimum cost to empty it.

## Input Format

The first line contains $T$ ($1\le T\le 100$), the number of independent tests. Each test is formatted as follows:

The first line contains an integer $N$. The second line contains $N$ integers, $a_1, a_2, \ldots, a_N$.

The third line contains an integer $M$. Then the next $M$ lines will contain $p_i, s_i, c_i$.

It is guaranteed that the cows will be able to remove all the haybales in every stack. Additionally, it is guaranteed that the sum of $N$ over all tests does not exceed $5\cdot 10^5$, and the sum of $M$ over all tests does not exceed $2500$.

## Output Format

For each test, print $N$ space-separated integers, the $i$-th integer being the cost of removing all the haybales in the $i$-th stack.

## Examples

**Input 1**

```
2
3
15 100 10
4
101 1 1
1 4 8
9 3 5
15 2 3
3
15 100 10
4
101 1 1
1 1 5
9 1 8
15 1 3
```

**Output 1**

```
29 155 21
73 328 50
```

## Note

**First test:** For the last stack of initial size $10$, we can hire cow $3$ once, which costs $5$ and will remove haybales twice (not thrice because the number of haybales turns to $8$ after the second one is removed). Then we can hire cow $2$ twice, removing the $8$ haybales, resulting in no haybales left. The total cost is $5+8+8=21$.

**Second test:** This satisfies $\max(s)=1$.

## Scoring

- Inputs 2-3: $a_i\le 100$.
- Inputs 4-5: $\max(s)=1$.
- Inputs 6-9: $\max(s)\le 4$.
- Inputs 10-15: $\max(s)\le 20$.
- Inputs 16-21: No additional constraints.

**Problem credits:** Sujay Konda

#include "testlib.h"
int main(int argc, char *argv[]) {
    registerValidation(argc, argv);
    int T = inf.readInt(1, 100, "T"); inf.readEoln();
    long long sumN = 0, sumM = 0;
    for (int tc = 1; tc <= T; tc++) {
        int N = inf.readInt(1, 500000, "N"); inf.readEoln();
        sumN += N;
        for (int i = 1; i <= N; i++) { inf.readInt(1, 1000000000, "a_i"); if (i < N) inf.readSpace(); }
        inf.readEoln();
        int M = inf.readInt(1, 2500, "M"); inf.readEoln();
        sumM += M;
        for (int i = 1; i <= M; i++) {
            inf.readInt(1, 1000000000, "p_i"); inf.readSpace();
            inf.readInt(1, 100, "s_i"); inf.readSpace();
            inf.readInt(1, 1000000000, "c_i"); inf.readEoln();
        }
    }
    ensuref(sumN <= 500000, "sum N %lld > 5e5", sumN);
    ensuref(sumM <= 2500, "sum M %lld > 2500", sumM);
    inf.readEof(); return 0;
}

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll INF = 1e18;

const int S = 100;

void upd(ll& a, ll b) { a = min(a, b); }

int main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    int t; cin >> t;
    while(t--) {
        ll n; cin >> n;
        vector<ll> a(n), oa(n);
        for(int i = 0; i < n; i++) {
            cin >> a[i];
            oa[i] = i;
        }
        sort(oa.begin(), oa.end(), [&] (ll x, ll y) { return a[x] < a[y]; });
        ll m; cin >> m;
        vector<ll> l(m), s(m), v(m), o(m);
        for(int i = 0; i < m; i++) {
            cin >> l[i] >> s[i] >> v[i];
            l[i]--;
            o[i] = i;
        }
        sort(o.begin(), o.end(), [&] (ll x, ll y) { return l[x] < l[y]; });
        int pl = 0;
        vector<ll> dp(S * S, INF); dp[0] = 0;
        vector<ll> best(S + 1, 1e15);

        // computes expdp which is used to query
        vector<ll> expdp;
        int bsi = 1;
        auto compute = [&] (int nsi) {
            for(int si = 1; si <= S; si++) {
                if(best[bsi] * si > bsi * best[si]) {
                    bsi = si;
                }
            }
            expdp = dp;
            for(int i = 0; i < expdp.size(); i++) {
                if(i + nsi < expdp.size()) {
                    upd(expdp[i + nsi], expdp[i] + best[nsi]);
                }
            }
        };
        // uses expdp to query
        auto query = [&] (ll x) {
            ll d = x - pl;
            ll t = max((d - (ll)expdp.size()) / bsi + 1, 0ll);
            return t * best[bsi] + expdp[d - bsi * t];
        };
        int k = 0;
        int lasts = 0;
        vector<ll> ans(n);
        for(int i : o) {
            compute(lasts);
            while(k < n && a[oa[k]] < l[i]) ans[oa[k]] = query(a[oa[k]]), k++;
            vector<ll> ndp(S * S, INF);
            for(int j = 0; j < S * S; j++) {
                ndp[j] = query(l[i] + j);
            }
            for(int j = 1; j < s[i]; j++) upd(ndp[j], ndp[0] + v[i]);
            upd(best[s[i]], v[i]);
            lasts = s[i];
            dp = ndp;
            pl = l[i];
        }
        compute(lasts);
        while(k < n) ans[oa[k]] = query(a[oa[k]]), k++;
        for(ll i : ans) cout << i << " ";
        cout << endl;
    }
}

verbatim earliest root score=100 submission #169143


Perfect Binary Trees

**Time limit:** 2 seconds    **Memory limit:** 512 megabytes

## Description

A *perfect binary tree* is a rooted tree where every non-leaf node has exactly two children and all leaf nodes are at an equal distance from the root.

An *unrooted perfect binary tree* is an unrooted tree that is a perfect binary tree when rooted at one of its nodes.

Bessie has a tree with $N$ ($1\le N\le 10^5$) nodes. Determine the number of ways to remove a subset of edges from the tree so that the resulting forest is a collection of unrooted perfect binary trees. As the answer may be very large, output the result modulo $10^9+7$.

## Input Format

The first line contains an integer $T$ ($1\le T\le 100$), the number of independent test cases.

The first line of each test case contains an integer $N$.

Each of the next $N-1$ lines of each test case contains two integers $u_i$ and $v_i$ ($1\le u_i, v_i\le N$) indicating an edge between nodes $u_i$ and $v_i$.

It is guaranteed that for each test case, the given edges form a tree with $N$ nodes.

Additionally, the sum of $N$ over all test cases does not exceed $2\cdot 10^5$.

## Output Format

For each test case, output a single integer: the number of subsets of edges that, when removed, result in a forest that is a collection of unrooted perfect binary trees, modulo $10^9+7$.

## Examples

**Input 1**

```
3
6
1 2
3 2
4 6
5 6
6 2
3
1 2
3 2
7
2 1
2 3
1 6
1 7
3 4
3 5
```

**Output 1**

```
8
2
14
```

## Note

In the first test case, Bessie can remove any of the following subsets of edges to get a forest of perfect binary trees:

- $(2,6)$
- $(1,2)$, $(2,3)$, $(2,6)$
- $(1,2)$, $(2,3)$, $(4,6)$
- $(1,2)$, $(2,3)$, $(5,6)$
- $(1,2)$, $(4,6)$, $(5,6)$
- $(2,6)$, $(4,6)$, $(5,6)$
- $(2,3)$, $(4,6)$, $(5,6)$
- $(1,2)$, $(2,3)$, $(2,6)$, $(4,6)$, $(5,6)$

The first subset results in two subtrees of height $1$, the last subset results in six subtrees of height $0$, and the other subsets result in three subtrees of height $0$ and one subtree of height $1$.

## Scoring

- Inputs 2-3: $N\le 15$.
- Inputs 4-5: No node is adjacent to more than two other nodes.
- Inputs 6-9: $N\le 1000$, the sum of $N$ does not exceed $2000$, and no node is adjacent to more than three other nodes.
- Inputs 10-13: No node is adjacent to more than three other nodes.
- Inputs 14-21: No additional constraints.

**Problem credits:** Avnith Vijayram

#include "testlib.h"
int main(int argc, char *argv[]) {
    registerValidation(argc, argv);
    int T = inf.readInt(1, 100, "T"); inf.readEoln();
    long long sumN = 0;
    for (int tc = 1; tc <= T; tc++) {
        int N = inf.readInt(1, 100000, "N"); inf.readEoln();
        sumN += N;
        for (int i = 1; i < N; i++) {
            int u = inf.readInt(1, N, "u"); inf.readSpace();
            int v = inf.readInt(1, N, "v"); inf.readEoln();
            ensuref(u != v, "test %d edge %d: self-loop", tc, i);
        }
    }
    ensuref(sumN <= 200000, "sum N %lld > 2e5", sumN);
    inf.readEof(); return 0;
}

#include <bits/stdc++.h>
using namespace std;

using ll = long long;
template<class T> using V = vector<T>;
const ll M = 1e9+7;
const int LGN = 17;

void solve() {
    int n; cin >> n;
    V<V<int>> adj(n);
    for (int i = 0; i < n-1; i++) {
        int u, v; cin >> u >> v; u--; v--;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }

    V<ll> ans(n, 0);
    V<V<ll>> dp(LGN, V<ll>(n, 0)), pd(LGN, V<ll>(n, 0));

    auto dfs = [&](auto&& dfs, int x, int p) -> void {
        ll sums[LGN][3][2];
        memset(sums, 0, sizeof(sums));
        for (int i = 0; i < LGN; i++) sums[i][0][0] = 1;

        for (auto y : adj[x]) {
            if (y == p) continue;
            dfs(dfs, y, x);

            for (int i = 0; i < LGN; i++) {
                for (int j = 2; j >= 0; j--) {
                    for (int k = 1; k >= 0; k--) {
                        if (j < 2) {
                            sums[i][j+1][k] += (i > 0 ? dp[i-1][y] : 0LL) * sums[i][j][k] % M;
                            sums[i][j+1][k] %= M;
                        }
                        if (k < 1) {
                            sums[i][j][k+1] += pd[i][y] * sums[i][j][k] % M;
                            sums[i][j][k+1] %= M;
                        }
                        sums[i][j][k] *= ans[y];
                        sums[i][j][k] %= M;
                    }
                }
            }
        }

        dp[0][x] += sums[0][0][0];
        for (int i = 0; i < LGN; i++) {
            if (i < LGN-1) dp[i+1][x] += sums[i+1][2][0];

            if (i < LGN-1) pd[i][x] += sums[i+1][1][0];
            if (i > 0) pd[i-1][x] += sums[i][1][1];

            ans[x] += dp[i][x];
            if (i == 0) ans[x] += sums[i][0][1];
            else ans[x] += sums[i][2][1];
        }
        for (int i = 0; i < LGN; i++) {
            dp[i][x] %= M;
            pd[i][x] %= M;
        }
        ans[x] %= M;
    };

    dfs(dfs, 0, -1);
    cout << ans[0] << endl;
}

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    int t; cin >> t;
    while (t--) solve();
}

verbatim earliest root score=100 submission #169144