Codeforces Round #615 (Div. 3)

Codeforces Round #615 (Div.3)

A

思路

假设 \(a \leq b \leq c\) ,使三人钱币数相等首先要满足 \(x \geq c - a + c - b\) ,其次要满足剩余量是 \(3\) 的整数倍。

Code

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

const int maxn = 1e5+10;
const int mod = 1e9+7;
const int maxm = 1e3+10;

int tree[maxn];
inline int lowbit(int x) { return x & -x; }
inline void modify(int x, int val) { for (int i = x; i < maxn; i += lowbit(i)) tree[i] += val; }
inline int query (int x) { int res = 0; for (int i = x; i ; i -= lowbit(i)) res += tree[i]; return res; }
ll ksm(ll a, ll n) { ll res = 1; while (n) { if (n & 1) res = res * a % mod; a = a * a % mod; n >>= 1; } return res; }
ll fac[maxn], inv[maxn];
void facInit() {
    fac[0] = 1;
    for (int i = 1; i < maxn; ++i) fac[i] = fac[i-1] * i % mod;
    inv[maxn-1] = ksm(fac[maxn-1], mod-2);
    for (int i = maxn-2; i >= 0; --i) inv[i] = inv[i+1] * (i+1) % mod;
}
ll C(int n, int m) { return fac[n] * inv[m] % mod * inv[n-m] % mod; }


int T, n, m;
int a[5];

int main() {
    scanf("%d", &T);
    while (T--) {
        for (int i = 1; i <= 3; ++i) scanf("%d", a+i);
        scanf("%d", &n);
        sort(a + 1, a + 1 + 3);
        ll need = 2ll * a[3] - a[2] - a[1];
        if (need <= n && (n - need) % 3 == 0) puts("YES");
        else puts("NO");
    }
    return 0;
}

B

思路

显然,\(R\) 的字典序小于 \(U\) ,所以在保证能走完全部点的前提下,先往右走再往上走。

Code

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

const int maxn = 1e5+10;
const int mod = 1e9+7;
const int maxm = 1e3+10;

int tree[maxn];
inline int lowbit(int x) { return x & -x; }
inline void modify(int x, int val) { for (int i = x; i < maxn; i += lowbit(i)) tree[i] += val; }
inline int query (int x) { int res = 0; for (int i = x; i ; i -= lowbit(i)) res += tree[i]; return res; }
ll ksm(ll a, ll n) { ll res = 1; while (n) { if (n & 1) res = res * a % mod; a = a * a % mod; n >>= 1; } return res; }
ll fac[maxn], inv[maxn];
void facInit() {
    fac[0] = 1;
    for (int i = 1; i < maxn; ++i) fac[i] = fac[i-1] * i % mod;
    inv[maxn-1] = ksm(fac[maxn-1], mod-2);
    for (int i = maxn-2; i >= 0; --i) inv[i] = inv[i+1] * (i+1) % mod;
}
ll C(int n, int m) { return fac[n] * inv[m] % mod * inv[n-m] % mod; }

struct node {
    int x, y;
    inline void read() { scanf("%d%d", &x, &y); }
    inline bool operator < (const node &phs) const { return x == phs.x? y < phs.y: x < phs.x; }
}a[maxn];

int T, n, m;
void solve() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i)
        a[i].read();
    sort(a + 1, a + 1 + n);
    bool fg = false;
    int x = 0, y = 0;
    string str = "";
    for (int i = 1; i <= n; ++i) {
        if (a[i].x >= x && a[i].y >= y) {
            for (int j = x + 1; j <= a[i].x; ++j) str.push_back('R');
            for (int j = y + 1; j <= a[i].y; ++j) str.push_back('U');
            x = a[i].x, y = a[i].y;
        } else {
            fg = 1;
            break;
        }
    }
    if (fg) puts("NO");
    else {
        puts("YES");
        cout << str << endl;
    }
}

int main() {
    scanf("%d", &T);
    while (T--)
        solve();
    return 0;
}

C

思路

只要 \(n\) 的质因子重组成三个不同数即可。

Code

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

const int maxn = 3e6+10;
const int mod = 1e9+7;
const int maxm = 1e3+10;
const int inf = 1e9;

int tree[maxn];
inline int lowbit(int x) { return x & -x; }
inline void modify(int x, int val) { for (int i = x; i < maxn; i += lowbit(i)) tree[i] += val; }
inline int query (int x) { int res = 0; for (int i = x; i ; i -= lowbit(i)) res += tree[i]; return res; }
ll ksm(ll a, ll n) { ll res = 1; while (n) { if (n & 1) res = res * a % mod; a = a * a % mod; n >>= 1; } return res; }
ll fac[maxn], inv[maxn];
void facInit() {
    fac[0] = 1;
    for (int i = 1; i < maxn; ++i) fac[i] = fac[i-1] * i % mod;
    inv[maxn-1] = ksm(fac[maxn-1], mod-2);
    for (int i = maxn-2; i >= 0; --i) inv[i] = inv[i+1] * (i+1) % mod;
}
ll C(int n, int m) { return fac[n] * inv[m] % mod * inv[n-m] % mod; }
int prime[maxn], pn;
bool nt[maxn];
void prePrime() {
    for (int i = 2; i < maxn; ++i) {
        if (!nt[i]) prime[pn++] = i;
        for (int j = 0; j < pn && prime[j] * i < maxn; ++j) {
            nt[i * prime[j]] = 1;
            if (i % prime[j] == 0) break;
        }
    }
}

struct node {
    int x, y;
    inline void read() { scanf("%d%d", &x, &y); }
    inline bool operator < (const node &phs) const { return x == phs.x? y < phs.y: x < phs.x; }
}a[maxn];

int T, n, m;
const int block = sqrt(inf);

void solve() {
    scanf("%d", &n);
    vector<int> q;
    for (int i = 0; i < pn && prime[i] <= n; ++i) {
        while(n % prime[i] == 0) {
            n /= prime[i];
            q.push_back(prime[i]);
        }
    }
    if(n > 1) q.push_back(n);
    int sz = q.size();
    if(sz < 3) puts("NO") ;
    else {
        int ans[5] = {1, 1, 1, 1, 1};
        int j = 0;
        for (int i = 1; i <= 3; ++i) {
            if (j < sz) ans[i] = q[j++];
            while(ans[i] == ans[i-1] && j < sz) ans[i] *= q[j++];
        }
        while(j < sz) ans[3] *= q[j++];
        sort(ans + 1, ans + 1 + 3);
        bool fg = false;
        for (int i = 1; i <= 3; ++i) {
            if(ans[i] == ans[i-1] || ans[i] < 2) {
                fg = 1;
                break;
            }
        }
        if(fg) puts("NO");
        else {
            puts("YES");
            printf("%d %d %d\n", ans[1], ans[2], ans[3]);
        }
    }
}

int main() {
    prePrime();
    scanf("%d", &T);
    while (T--)
        solve();
    return 0;
}

D

思路

简单分析后,发现这是个 \(m\) 的剩余系,所以,每次 query 的答案模 \(m\) 的结果为即为 \(0 \sim m-1\) 中出现次数最少的那个。

我们随便用线段树维护一下即可。

Code

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

const int maxn = 3e6+10;
const int mod = 1e9+7;
const int maxm = 1e3+10;
const int inf = 1e9;

int tree[maxn];
inline int lowbit(int x) { return x & -x; }
inline void modify(int x, int val) { for (int i = x; i < maxn; i += lowbit(i)) tree[i] += val; }
inline int query (int x) { int res = 0; for (int i = x; i ; i -= lowbit(i)) res += tree[i]; return res; }
ll ksm(ll a, ll n) { ll res = 1; while (n) { if (n & 1) res = res * a % mod; a = a * a % mod; n >>= 1; } return res; }
ll fac[maxn], inv[maxn];
void facInit() {
    fac[0] = 1;
    for (int i = 1; i < maxn; ++i) fac[i] = fac[i-1] * i % mod;
    inv[maxn-1] = ksm(fac[maxn-1], mod-2);
    for (int i = maxn-2; i >= 0; --i) inv[i] = inv[i+1] * (i+1) % mod;
}
ll C(int n, int m) { return fac[n] * inv[m] % mod * inv[n-m] % mod; }
int prime[maxn], pn;
bool nt[maxn];
void prePrime() {
    for (int i = 2; i < maxn; ++i) {
        if (!nt[i]) prime[pn++] = i;
        for (int j = 0; j < pn && prime[j] * i < maxn; ++j) {
            nt[i * prime[j]] = 1;
            if (i % prime[j] == 0) break;
        }
    }
}

int T, n, m;

struct node {
    int l, r, val, pos;
}tr[maxn<<2];

#define ls i<<1
#define rs i<<1|1
void pushup(int i) {
    if(tr[ls].val > tr[rs].val) {
        tr[i].val = tr[rs].val;
        tr[i].pos = tr[rs].pos;
    } else {
        tr[i].val = tr[ls].val;
        tr[i].pos = tr[ls].pos;
    }
}

void build(int l, int r, int i) {
    tr[i] = node{l, r, inf, inf};
    if(l == r) { tr[i].val = 0, tr[i].pos = l; return; }
    int mid = l + r >> 1;
    build(l, mid, ls); build(mid+1, r, rs);
    pushup(i);
}

void update(int pos, int i) {
    if(tr[i]. l == tr[i].r) {
        ++tr[i].val;
        return;
    }
    int mid = tr[i].l + tr[i].r >> 1;
    if(pos <= mid)  update(pos, ls);
    else update(pos, rs);
    pushup(i);
}

void solve() {
    scanf("%d%d", &n, &m);
    build(1, m, 1);
    for (int x, i = 1; i <= n; ++i) {
        scanf("%d", &x);
        x %= m; ++x;
        update(x, 1);
        printf("%d\n", tr[1].pos-1 + m * tr[1].val);
    }
}

int main() {
        solve();
    return 0;
}

E

思路

题目中有两种操作:

一、将任意一个数更改为另一个数。

二、将某一列循环向上拨动一个位置。

所以我们可以每一列拆开处理。

对于每一列中的每个数,我们记录一下这个数是否应为这一列的数字,若不是则pass,若是则统计假如将他拨动到对应位置的第一行现在在第几行即可。

Code

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

const int maxn = 2e5+10;
const int mod = 1e9+7;
const int maxm = 1e3+10;
const int inf = 1e9;

int tree[maxn];
inline int lowbit(int x) { return x & -x; }
inline void modify(int x, int val) { for (int i = x; i < maxn; i += lowbit(i)) tree[i] += val; }
inline int query (int x) { int res = 0; for (int i = x; i ; i -= lowbit(i)) res += tree[i]; return res; }
ll ksm(ll a, ll n) { ll res = 1; while (n) { if (n & 1) res = res * a % mod; a = a * a % mod; n >>= 1; } return res; }
ll fac[maxn], inv[maxn];
void facInit() {
    fac[0] = 1;
    for (int i = 1; i < maxn; ++i) fac[i] = fac[i-1] * i % mod;
    inv[maxn-1] = ksm(fac[maxn-1], mod-2);
    for (int i = maxn-2; i >= 0; --i) inv[i] = inv[i+1] * (i+1) % mod;
}
ll C(int n, int m) { return fac[n] * inv[m] % mod * inv[n-m] % mod; }
int prime[maxn], pn;
bool nt[maxn];
void prePrime() {
    for (int i = 2; i < maxn; ++i) {
        if (!nt[i]) prime[pn++] = i;
        for (int j = 0; j < pn && prime[j] * i < maxn; ++j) {
            nt[i * prime[j]] = 1;
            if (i % prime[j] == 0) break;
        }
    }
}

int T, n, m;
int cnt[maxn];
vector<int> vec[maxn];

void solve() {
    scanf("%d%d", &n, &m);
    ll res = 0;
    for (int i = 1; i <= n; ++i) for (int x, j = 1; j <= m; ++j) scanf("%d", &x), vec[j].push_back(x);
    for (int i = 1; i <= m; ++i) {
        for (int j = 1; j <= n; ++j) cnt[j] = 0;
        for (int j = 1; j <= n; ++j) {
            int x = vec[i][j-1];
            if (x % m == i % m && x <= n*m) {
                int pos = j - (x +m-1)/ m + 1;
                if (pos <= 0) pos += n;
                ++cnt[pos];
            }
        }
        int sum = inf;
        for (int j = 1; j <= n; ++j) sum = min(sum, j - 1 + n - cnt[j]);
        res += sum;
    }
    printf("%lld\n", res);
}

int main() {
    solve();
    return 0;
}

F

思路

抽象后的题意即为从该树找到三个节点,若他们的 \(lca\)\(x\) ,使得这三个点到 \(x\) 点的边的并集的数量最大。

首先可以固定三个点中的两个点分别是树直径的两个端点,剩余的一个点则为到直径距离最远的一个点。

Code

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

const int maxn = 3e6+10;
const int mod = 1e9+7;
const int maxm = 1e3+10;
const int inf = 1e9;

int tree[maxn];
inline int lowbit(int x) { return x & -x; }
inline void modify(int x, int val) { for (int i = x; i < maxn; i += lowbit(i)) tree[i] += val; }
inline int query (int x) { int res = 0; for (int i = x; i ; i -= lowbit(i)) res += tree[i]; return res; }
ll ksm(ll a, ll n) { ll res = 1; while (n) { if (n & 1) res = res * a % mod; a = a * a % mod; n >>= 1; } return res; }
ll fac[maxn], inv[maxn];
void facInit() {
    fac[0] = 1;
    for (int i = 1; i < maxn; ++i) fac[i] = fac[i-1] * i % mod;
    inv[maxn-1] = ksm(fac[maxn-1], mod-2);
    for (int i = maxn-2; i >= 0; --i) inv[i] = inv[i+1] * (i+1) % mod;
}
ll C(int n, int m) { return fac[n] * inv[m] % mod * inv[n-m] % mod; }
int prime[maxn], pn;
bool nt[maxn];
void prePrime() {
    for (int i = 2; i < maxn; ++i) {
        if (!nt[i]) prime[pn++] = i;
        for (int j = 0; j < pn && prime[j] * i < maxn; ++j) {
            nt[i * prime[j]] = 1;
            if (i % prime[j] == 0) break;
        }
    }
}

int n;
vector<int> g[maxn];
bool vis[maxn];
int f[maxn], dep[maxn];

void dfs(int x, int fa = 0) {
    f[x] = fa;
    if(vis[x]) dep[x] = 1;
    else dep[x] = dep[fa] + 1;
    for (auto v: g[x]) {
        if (v == fa) continue;
        dfs(v, x);
    }
}


void solve() {
    scanf("%d", &n);
    for (int u, v, i = 1; i < n; ++i) {
        scanf("%d%d", &u, &v);
        g[u].push_back(v);
        g[v].push_back(u);
    }

    int a = 0, b = 0, c = 0, ans = 0;

    dfs(1);
    for (int i = 1; i <= n; ++i) if (dep[i] > dep[a]) a = i;

    dfs(a);
    for (int i = 1; i <= n; ++i) if (dep[i] > dep[b] && i != a) b = i;
    int p = b;
    while(p) {
        vis[p] = 1;
        p = f[p];
        ++ans;
    }
    --ans;
    dfs(a);
    for (int i = 1; i <= n; ++i) if (dep[i] > dep[c] && i != a && i != b) c = i;

    p = c;
    while(p) {
        if (vis[p]) break;
        ++ans;
        p = f[p];
    }

    printf("%d\n%d %d %d\n", ans, a, b, c);

}

int main() {
    solve();
    return 0;
}
posted @ 2020-01-27 20:01  Acerkoo  阅读(196)  评论(0编辑  收藏  举报