Atcoder Codefestival Exhibition/Team Relay/Tournament Round 简要题解

来源:互联网 发布:win10苹果usb共享网络 编辑:程序博客网 时间:2024/06/08 16:51

Exhibition

Awkward

考虑容斥,至少某些限制不满足。

把不满足的边画出来,发现是若干条不相交路径,DP即可。

#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline int Read(){    int x = 0, f = 1, c = getchar();    for (; !isdigit(c); c = getchar())        if (c == '-')            f = -1;    for (;  isdigit(c); c = getchar())        x = x * 10 + c - '0';    return x * f;}const int MAXN = 2005;const int mod = 1e9 + 7;int n, siz[MAXN], g[MAXN][3], f[MAXN][MAXN][3];vector <int> adj[MAXN];inline void DFS(int x){    siz[x] = 1, f[x][1][0] = 1;    for (auto y : adj[x])    {        DFS(y), mcpy(g, f[x]), mset(f[x], 0);        for (int dx = 0; dx <= 2; dx ++)            for (int dy = 0; dy <= 2; dy ++)                for (int dz = 0; dz <= 1; dz ++)                    if (!dz || (dx < 2 && dy < 2))                        for (int i = 1; i <= siz[x]; i ++)                            for (int j = 1; j <= siz[y]; j ++)                            {                                int cur = 1;                                if (dz)                                {                                    cur = mod - 1;                                    if (!dx && !dy)                                        cur = (cur << 1) % mod;                                    if (dx && dy)                                        cur = cur >> 1;                                }                                f[x][i + j - dz][dx + dz] = (1LL * g[i][dx] * f[y][j][dy] % mod * cur + f[x][i + j - dz][dx + dz]) % mod;                            }        siz[x] += siz[y];    }}int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#endif    n = Read();    for (int i = 2; i <= n; i ++)        adj[Read()].pb(i);    DFS(1);    int ret = 0;    for (int i = 0, cur = 1; i <= n; i ++, cur = 1LL * cur * i % mod)        for (int j = 0; j <= 2; j ++)            ret = (1LL * f[1][i][j] * cur + ret) % mod;    return printf("%d\n", ret), 0;}

Increment and Swap

从左往右考虑,假设当前考虑第i个数,记costv=v+i1j=1[aj>v],可以证明每次贪心取costv最小的最优,操作后将costj(1j<ai)加一,然后线段树维护。

证明:考虑反证,如果存在一个更优的v更优,显然v<v

接下来归纳,首先i=n时成立,如果i=k+1时成立,那么我们只需要证明i=k时成立即可。

注意到costv>costv,而在之后的操作中,仍然有costi>costv(1i<v)(考虑每次操作的影响),而之后贪心是对的,所以这一步贪心也是对的。

#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline int Read(){    int x = 0, f = 1, c = getchar();    for (; !isdigit(c); c = getchar())        if (c == '-')            f = -1;    for (;  isdigit(c); c = getchar())        x = x * 10 + c - '0';    return x * f;}const int MAXN = 200005;int n, m, a[MAXN], b[MAXN], tag[MAXN << 2];pii val[MAXN << 2];LL ans;inline void Build(int x, int l, int r){    val[x] = mp(b[l], l);    if (l == r)        return ;    int mid = l + r >> 1;    Build(x << 1, l, mid), Build(x << 1 | 1, mid + 1, r);}inline void Modify(int x, int l, int r, int ql, int qr){    if (l == ql && r == qr)        return (void)(val[x].xx ++, tag[x] ++);    if (tag[x])        val[x << 1].xx += tag[x], tag[x << 1] += tag[x], val[x << 1 | 1].xx += tag[x], tag[x << 1 | 1] += tag[x], tag[x] = 0;    int mid = l + r >> 1;    if (qr <= mid)        Modify(x << 1, l, mid, ql, qr);    else if (ql > mid)        Modify(x << 1 | 1, mid + 1, r, ql, qr);    else        Modify(x << 1, l, mid, ql, mid), Modify(x << 1 | 1, mid + 1, r, mid + 1, qr);    val[x] = min(val[x << 1], val[x << 1 | 1]);}inline pii Query(int x, int l, int r, int ql, int qr){    if (l == ql && r == qr)        return val[x];    if (tag[x])        val[x << 1].xx += tag[x], tag[x << 1] += tag[x], val[x << 1 | 1].xx += tag[x], tag[x << 1 | 1] += tag[x], tag[x] = 0;    int mid = l + r >> 1;    if (qr <= mid)        return Query(x << 1, l, mid, ql, qr);    if (ql > mid)        return Query(x << 1 | 1, mid + 1, r, ql, qr);    return min(Query(x << 1, l, mid, ql, mid), Query(x << 1 | 1, mid + 1, r, mid + 1, qr));}int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#endif    n = Read();    for (int i = 1; i <= n; i ++)        a[i] = b[i] = Read(), ans -= a[i];    sort(b + 1, b + n + 1), m = unique(b + 1, b + n + 1) - b - 1, Build(1, 1, m);    for (int i = 1; i <= n; i ++)    {        pii val = Query(1, 1, m, lower_bound(b + 1, b + m + 1, a[i]) - b, m);        ans += val.xx;        if (val.yy > 1)            Modify(1, 1, m, 1, val.yy - 1);    }    return printf("%lld\n", ans), 0;}

Tournament Round

Colorful MST

把颜色相同的缩起来,跑MST,两个并查集维护原图连通性和颜色连通性即可。

#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline int Read(){    int x = 0, f = 1, c = getchar();    for (; !isdigit(c); c = getchar())        if (c == '-')            f = -1;    for (;  isdigit(c); c = getchar())        x = x * 10 + c - '0';    return x * f;}const int MAXN = 100005;struct Edge{    int u, v, w;    bool operator < (const Edge &b) const    {        return w < b.w;    }} e[MAXN];int n, m, c, f[MAXN], g[MAXN], col[MAXN];LL ret;inline int FindF(int x){    while (x ^ f[x])        x = f[x] = f[f[x]];    return x;}inline int FindG(int x){    while (x ^ g[x])        x = g[x] = g[g[x]];    return x;}int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#endif    n = Read(), m = Read(), c = Read() - 1;    for (int i = 1; i <= n; i ++)        col[i] = Read(), f[i] = i;    for (int i = 1; i <= c + 1; i ++)        g[i] = i;    for (int i = 1; i <= m; i ++)        e[i].u = Read(), e[i].v = Read(), e[i].w = Read();    sort(e + 1, e + m + 1);    for (int i = 1; i <= m; i ++)    {        if (!c)            break;        int u = FindF(e[i].u), v = FindF(e[i].v), cu = col[u], cv = col[v];        if (u == v)            continue;        f[u] = v, col[v] = cv ? cv : cu;        if (cu && cv)        {            cu = FindG(cu), cv = FindG(cv);            if (cu == cv)                continue;            g[cu] = cv, c --, ret += e[i].w;        }        else            c --, ret += e[i].w;    }    if (c)        ret = -1;    return printf("%lld\n", ret), 0;}

Many Swaps Sorting

注意到只用1n1就能完成了,冒泡排序。

#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline int Read(){    int x = 0, f = 1, c = getchar();    for (; !isdigit(c); c = getchar())        if (c == '-')            f = -1;    for (;  isdigit(c); c = getchar())        x = x * 10 + c - '0';    return x * f;}const int MAXN = 205;vector <int> ans;int n, a[MAXN];inline void Solve(int x){    ans.pb(x);    for (int i = x; i < n; i ++)        swap(a[i], a[i - x]);}int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#endif    n = Read();    for (int i = 0; i < n; i ++)        a[i] = Read();    while (!is_sorted(a, a + n))        if (a[0] && a[0] < a[n - 1])            Solve(n - 1);        else            Solve(1);    printf("%d\n", ans.size());    for (int i = 0; i < ans.size(); i ++)        printf("%d\n", ans[i]);    return 0;}

Paired Parentheses

只需要满足:s1=t1,s2n=t2n,并且相等的对数和不相等的对数都是偶数即可,构造很显然。

线段树维护。

#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline int Read(){    int x = 0, f = 1, c = getchar();    for (; !isdigit(c); c = getchar())        if (c == '-')            f = -1;    for (;  isdigit(c); c = getchar())        x = x * 10 + c - '0';    return x * f;}const int MAXN = 200005;LL val_a[MAXN << 2], val_b[MAXN << 2];int n, m, a[MAXN], b[MAXN];inline void Build(int x, int l, int r){    if (l == r)        return (void)(val_a[x] = a[l], val_b[x] = b[l]);    int mid = l + r >> 1;    Build(x << 1, l, mid), Build(x << 1 | 1, mid + 1, r);    val_a[x] = max(val_a[x << 1] + val_a[x << 1 | 1], val_b[x << 1] + val_b[x << 1 | 1]);    val_b[x] = max(val_b[x << 1] + val_a[x << 1 | 1], val_a[x << 1] + val_b[x << 1 | 1]);}inline void Modify(int x, int l, int r, int p){    if (l == r)        return (void)(val_a[x] = a[l], val_b[x] = b[l]);    int mid = l + r >> 1;    if (p <= mid)        Modify(x << 1, l, mid, p);    else        Modify(x << 1 | 1, mid + 1, r, p);    val_a[x] = max(val_a[x << 1] + val_a[x << 1 | 1], val_b[x << 1] + val_b[x << 1 | 1]);    val_b[x] = max(val_b[x << 1] + val_a[x << 1 | 1], val_a[x << 1] + val_b[x << 1 | 1]);}int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#endif    n = Read(), m = Read();    for (int i = 1; i <= n << 1; i ++)        a[i] = Read();    for (int i = 1; i <= n << 1; i ++)        b[i] = Read();    if (n == 1)    {        while (m --)        {            int p = Read(), x = Read(), y = Read();            a[p] = x, b[p] = y;            printf("%d\n", a[1] + a[n << 1]);        }        return 0;    }    Build(1, 2, (n << 1) - 1);    while (m --)    {        int p = Read(), x = Read(), y = Read();        a[p] = x, b[p] = y;        if (p > 1 && p < n << 1)            Modify(1, 2, (n << 1) - 1, p);        printf("%lld\n", a[1] + a[n << 1] + val_a[1]);    }    return 0;}

Ancient Tree Record

用相邻两个点的权值可以求出这条边的权值,两边大小相等的边最多一条,最后暴力求。

#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline LL Read(){    LL x = 0; int f = 1, c = getchar();    for (; !isdigit(c); c = getchar())        if (c == '-')            f = -1;    for (;  isdigit(c); c = getchar())        x = x * 10 + c - '0';    return x * f;}const int MAXN = 100005;int n, e_cnt = 1, p[MAXN << 1], v[MAXN << 1], hed[MAXN], siz[MAXN];LL cur, a[MAXN], val[MAXN];inline void Addedge(int x, int y){    e_cnt ++, p[e_cnt] = y, v[e_cnt] = hed[x], hed[x] = e_cnt;    e_cnt ++, p[e_cnt] = x, v[e_cnt] = hed[y], hed[y] = e_cnt;}inline void DFS(int x, int par){    siz[x] = 1;    for (int i = hed[x]; i; i = v[i])        if (p[i] ^ par)        {            DFS(p[i], x);            if (siz[p[i]] << 1 ^ n)                val[i >> 1] = (a[x] - a[p[i]]) / ((siz[p[i]] << 1) - n);            siz[x] += siz[p[i]];        }}inline void Cal(int x, int par){    siz[x] = 1;    for (int i = hed[x]; i; i = v[i])        if (p[i] ^ par)            Cal(p[i], x), cur += siz[p[i]] * val[i >> 1], siz[x] += siz[p[i]];}int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#endif    n = Read();    for (int i = 1; i < n; i ++)        Addedge(Read(), Read());    for (int i = 1; i <= n; i ++)        a[i] = Read();    DFS(1, 0);    for (int i = 1; i < n; i ++)        if (!val[i])        {            int u = p[i << 1], v = p[i << 1 | 1];            Cal(u, v), Cal(v, u);            val[i] = (a[u] - cur) / siz[v];        }    for (int i = 1; i < n; i ++)        printf("%lld\n", val[i]);    return 0;}

Black Cats Deployment

将边从大到小加入,启发式合并。

#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline int Read(){    int x = 0, f = 1, c = getchar();    for (; !isdigit(c); c = getchar())        if (c == '-')            f = -1;    for (;  isdigit(c); c = getchar())        x = x * 10 + c - '0';    return x * f;}const int MAXN = 100005;struct Edge{    int u, v, w;    bool operator < (const Edge &b) const    {        return w > b.w;    }} e[MAXN];LL ans[MAXN], tag[MAXN];vector <int> g[MAXN];int n, f[MAXN];inline int Find(int x){    while (x ^ f[x])        x = f[x] = f[f[x]];    return x;}inline void Merge(int x, int y, int w){    x = Find(x), y = Find(y);    if (g[x].size() < g[y].size())        swap(x, y);    for (auto i : g[y])        ans[i] += tag[y] - tag[x], ans[i] += 1LL * (g[x].size() - g[y].size()) * w;    tag[x] += 1LL * g[y].size() * w;    for (auto i : g[y])        g[x].pb(i);    f[y] = x;}int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#endif    n = Read();    for (int i = 1; i <= n; i ++)        f[i] = i, g[i].pb(i);    for (int i = 1; i < n; i ++)        e[i].u = Read(), e[i].v = Read(), e[i].w = Read();    sort(e + 1, e + n);    for (int i = 1; i < n; i ++)        Merge(e[i].u, e[i].v, e[i].w);    for (int i = 1; i <= n; i ++)        printf("%lld\n", ans[i] + tag[Find(i)]);    return 0;}

Unicyclic Graph Counting

将环缩起来,定义其prufer序列是不删去环上点,并且最后一个点在环上,那么不难发现环上的点出现了d2次, 非环上的点出现了d1次。

f(i,j,0/1)表示前i个点,有j个点在环上,是否prufer序列的最后一个点出现过的方案数。

#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline int Read(){    int x = 0, f = 1, c = getchar();    for (; !isdigit(c); c = getchar())        if (c == '-')            f = -1;    for (;  isdigit(c); c = getchar())        x = x * 10 + c - '0';    return x * f;}const int MAXN = 305;const int mod = 1e9 + 7;int n, a[MAXN], fac[MAXN], inv[MAXN], f[MAXN][MAXN][2];int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#endif    n = Read(), fac[0] = fac[1] = inv[0] = inv[1] = 1;    for (int i = 2; i <= n; i ++)        fac[i] = 1LL * fac[i - 1] * i % mod, inv[i] = 1LL * (mod - mod / i) * inv[mod % i] % mod;    bool sam = true;    for (int i = 1; i <= n; i ++)        inv[i] = 1LL * inv[i - 1] * inv[i] % mod, a[i] = Read(), sam &= a[i] == 2;    if (sam)        return printf("%d\n", 1LL * fac[n - 1] * inv[2] % mod), 0;    f[0][0][0] = 1;    for (int i = 0; i < n; i ++)        for (int j = 0; j <= i; j ++)            for (int k = 0; k < 2; k ++)                if (f[i][j][k])                {                    f[i + 1][j][k] = (f[i + 1][j][k] + f[i][j][k]) % mod;                    if (a[i + 1] >= 2)                        f[i + 1][j + 1][k] = (1LL * f[i][j][k] * (a[i + 1] - 1) + f[i + 1][j + 1][k]) % mod;                    if (a[i + 1] >= 3 && !k)                        f[i + 1][j + 1][1] = (1LL * f[i][j][k] * (a[i + 1] - 1) * (a[i + 1] - 2) + f[i + 1][j + 1][1]) % mod;                }    int ans = 0, cur = 1;    for (int i = 1; i <= n; i ++)        cur = 1LL * cur * inv[a[i] - 1] % mod;    for (int i = 3; i < n; i ++)        if (f[n][i][1])            ans = (1LL * fac[i - 1] % mod * f[n][i][1] % mod * fac[n - i - 1] % mod * inv[2] + ans) % mod;    return printf("%d\n", 1LL * ans * cur % mod), 0;}

Team Relay

Kaiden

分类讨论一下。

#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline LL Read(){    LL x = 0; int f = 1, c = getchar();    for (; !isdigit(c); c = getchar())        if (c == '-')            f = -1;    for (;  isdigit(c); c = getchar())        x = x * 10 + c - '0';    return x * f;}int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#endif    LL k = Read(), a = Read(), b = Read();    if (a >= k)        return puts("1"), 0;    if (a <= b)        return puts("-1"), 0;    return printf("%lld\n", 2 * ((k - b - 1) / (a - b)) + 1), 0;}

Evergrowing Tree

暴力。

#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline int Read(){    int x = 0, f = 1, c = getchar();    for (; !isdigit(c); c = getchar())        if (c == '-')            f = -1;    for (;  isdigit(c); c = getchar())        x = x * 10 + c - '0';    return x * f;}int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#endif    int n = Read(), m = Read();    if (n == 1)    {        while (m --)            printf("%d\n", min(Read(), Read()));        return 0;    }    while (m --)    {        int a = Read(), b = Read();        while (a ^ b)        {            if (a < b)                swap(a, b);            a = (a + n - 2) / n;        }        printf("%d\n", a);    }    return 0;}

Garden

二分。

#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline LL Read(){    LL x = 0; int f = 1, c = getchar();    for (; !isdigit(c); c = getchar())        if (c == '-')            f = -1;    for (;  isdigit(c); c = getchar())        x = x * 10 + c - '0';    return x * f;}const int MAXN = 100005;int n, m, d[MAXN];LL w[MAXN];inline bool Chk(LL x){    LL cur = 0;    for (int i = 1; i <= n; i ++)    {        if (x >= w[i])            cur += (x - w[i]) / d[i] + 1;        if (cur >= m)            return true;    }    return false;}int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#endif    n = Read(), m = Read();    for (int i = 1; i <= n; i ++)        w[i] = Read(), d[i] = Read();    LL l = 0, r = 1LL << 61, ret = r;    while (l <= r)    {        LL mid = l + r >> 1;        if (Chk(mid))            ret = mid, r = mid - 1;        else            l = mid + 1;    }    return printf("%lld\n", ret), 0;}

Shock

贪心往原先size大的加,最后变成两个连通块连成完全图。

#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline int Read(){    int x = 0, f = 1, c = getchar();    for (; !isdigit(c); c = getchar())        if (c == '-')            f = -1;    for (;  isdigit(c); c = getchar())        x = x * 10 + c - '0';    return x * f;}const int MAXN = 100005;int n, m, f[MAXN], siz[MAXN];inline int Find(int x){    while (x ^ f[x])        x = f[x] = f[f[x]];    return x;}inline void Merge(int x, int y){    x = Find(x), y = Find(y);    if (x == y)        return ;    siz[x] += siz[y], f[y] = x;}int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#endif    n = Read(), m = Read();    for (int i = 1; i <= n; i ++)        f[i] = i, siz[i] = 1;    for (int i = 1; i <= m; i ++)        Merge(Read(), Read());    for (int i = 1; i <= n; i ++)        if (Find(i) == i && (Find(i) ^ Find(1)) && (Find(i) ^ Find(2)))            if (siz[Find(1)] >= siz[Find(2)])                siz[Find(1)] += siz[i];            else                siz[Find(2)] += siz[i];    LL ret = 1LL * siz[Find(1)] * (siz[Find(1)] - 1) / 2 + 1LL * siz[Find(2)] * (siz[Find(2)] - 1) / 2;    return printf("%lld\n", ret - m), 0;}

White and Blue

WW+BP100,化一下式子,按照每个人的影响排序,贪心选取。

#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline int Read(){    int x = 0, f = 1, c = getchar();    for (; !isdigit(c); c = getchar())        if (c == '-')            f = -1;    for (;  isdigit(c); c = getchar())        x = x * 10 + c - '0';    return x * f;}const int MAXN = 100005;int n, p;LL cur;struct Node{    int w, b;    bool operator < (const Node &c) const    {        return 1LL * w * (100 - p) + 1LL * b * p > 1LL * c.w * (100 - p) + 1LL * c.b * p;    }} a[MAXN];int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#endif    n = Read(), p = Read();    for (int i = 1; i <= n; i ++)        a[i].w = Read(), a[i].b = Read(), cur -= a[i].b;    sort(a + 1, a + n + 1);    cur *= p;    for (int i = 1; i <= n; i ++)        if ((cur += 1LL * a[i].w * (100 - p) + 1LL * a[i].b * p) >= 0)            return printf("%d\n", i), 0;}

Capture

sumrsuml1xr+xl1最大,扫一遍。

#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline LL Read(){    LL x = 0; int f = 1, c = getchar();    for (; !isdigit(c); c = getchar())        if (c == '-')            f = -1;    for (;  isdigit(c); c = getchar())        x = x * 10 + c - '0';    return x * f;}LL x, s, ans, cur = LLONG_MIN;int n;int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#endif    n = Read();    for (int i = 1; i <= n; i ++)        x = Read(), cur = max(cur, x - s), s += Read(), ans = max(ans, cur + s - x);    return printf("%lld\n", ans), 0;}

Coinage

不妨设s+tt+s,那么s越多越优。

#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline int Read(){    int x = 0, f = 1, c = getchar();    for (; !isdigit(c); c = getchar())        if (c == '-')            f = -1;    for (;  isdigit(c); c = getchar())        x = x * 10 + c - '0';    return x * f;}int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#endif    string s, t, ans = "";    int n = Read(), x = 0;    cin >> s >> t;    if (s + t > t + s)        swap(s, t);    for (int i = 1; i * s.length() <= n; i ++)        if ((n - i * s.length()) % t.length() == 0)            x = i;    for (int i = 1; i <= x; i ++)        ans += s;    while (ans.length() ^ n)        ans += t;    cout << ans << endl;    return 0;}

Akashic Records

根号以下的暴力枚举次幂,根号以上的独立,贪心即可。

#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline int Read(){    int x = 0, f = 1, c = getchar();    for (; !isdigit(c); c = getchar())        if (c == '-')            f = -1;    for (;  isdigit(c); c = getchar())        x = x * 10 + c - '0';    return x * f;}const int MAXN = 305;const int p[7] = {2, 3, 5, 7, 11, 13, 17};const int lim[7] = {9, 6, 4, 3, 3, 3, 3};int n, ans, cur[7], w[MAXN], val[MAXN], a[MAXN][8];inline void Solve(){    int now = 0;    for (int i = 1; i <= 300; i ++)        w[i] = 0;    for (int i = 1; i <= n; i ++)    {        bool flg = true;        for (int j = 0; j < 7 && flg; j ++)            flg &= cur[j] >= a[i][j];        if (flg)        {            if (a[i][7] ^ 1)                w[a[i][7]] += val[i];            else                now += val[i];        }    }    for (int i = 1; i <= 300; i ++)        now += max(w[i], 0);    ans = max(ans, now);}inline void DFS(int x){    if (x == 7)        Solve();    else        for (cur[x] = 0; cur[x] < lim[x]; cur[x] ++)            DFS(x + 1);}int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#endif    n = Read();    for (int i = 1; i <= n; i ++)    {        a[i][7] = Read(), val[i] = Read();        for (int j = 0; j < 7; j ++)            while (a[i][7] % p[j] == 0)                a[i][7] /= p[j], a[i][j] ++;    }    DFS(0);    return printf("%d\n", ans), 0;}

Nice to Meet You

补集转化,求两个人不能到达同一个地点的概率。

记两个人能到达的地点集合为AB,显然AB之间没有边,其概率为fAfB12EA+EBfS表示只用S中的点1或者2能到达的点集为S的概率,ES表示一个端点在S内,另一个不在的边数。

计算f可以枚举子集容斥。

#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline int Read(){    int x = 0, f = 1, c = getchar();    for (; !isdigit(c); c = getchar())        if (c == '-')            f = -1;    for (;  isdigit(c); c = getchar())        x = x * 10 + c - '0';    return x * f;}const int MAXN = 20;const int MAXM = 32770;const int mod = 1e9 + 7;int n, m, bin[MAXN * MAXN], e[MAXM], f[MAXM];inline int F(int x, int y){    return e[x | y] - e[x] - e[y];}int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#endif    n = Read(), m = Read(), bin[0] = 1;    for (int i = 1; i <= m; i ++)        bin[i] = 1LL * bin[i - 1] * (mod + 1) / 2 % mod;    for (int i = 1; i <= m; i ++)        for (int j = 0, x = Read() - 1, y = Read() - 1; j < 1 << n; j ++)            if ((j >> x & 1) && (j >> y & 1))                e[j] ++;    for (int i = 0; i < 1 << n; i ++)        if ((i & 1) && !(i & 2))        {            f[i] = 1;            for (int j = i - 1; j; j = j - 1 & i)                if (j & 1)                    f[i] = (f[i] - 1LL * f[j] * bin[F(j, j ^ i)] % mod + mod) % mod;        }        else if ((i & 2) && !(i & 1))        {            f[i] = 1;            for (int j = i - 1; j; j = j - 1 & i)                if (j & 2)                    f[i] = (f[i] - 1LL * f[j] * bin[F(j, j ^ i)] % mod + mod) % mod;        }    for (int i = 0; i < 1 << n; i ++)        f[i] = 1LL * f[i] * bin[F(i, (1 << n) - 1 ^ i)] % mod;    int ans = 1;    for (int i = 0; i < 1 << n; i ++)        if ((i & 1) && !(i & 2))            for (int j = (1 << n) - 1 - i; j; j = j - 1 & (1 << n) - 1 - i)                if ((j & 2) && !(j & 1))                    if (!F(i, j))                        ans = (ans - 1LL * f[i] * f[j] % mod + mod) % mod;    for (int i = 1; i <= m; i ++)        ans = (ans << 1) % mod;    return printf("%d\n", ans), 0;}

Indifferent

打表发现第i大的贡献为2ni2n1

证明可以归纳。

#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair <int, int> pii;inline int Read(){    int x = 0, f = 1, c = getchar();    for (; !isdigit(c); c = getchar())        if (c == '-')            f = -1;    for (;  isdigit(c); c = getchar())        x = x * 10 + c - '0';    return x * f;}const int MAXN = 200005;int n, a[MAXN];int main(){#ifdef wxh010910    freopen("data.in", "r", stdin);#endif    n = Read();    for (int i = 0; i < n << 1; i ++)        a[i] = Read();    sort(a, a + (n << 1));    LL ans = 0;    for (int i = 0; i < n << 1; i ++)        ans += 1LL * a[i] * i;    return printf("%.9lf\n", (double)ans / ((n << 1) - 1)), 0;}
原创粉丝点击