AtCoder Beginner Contest 165

传送门

A - We Love Golf

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int main() {
    int k, a, b;
    scanf("%d%d%d", &k, &a, &b);
    bool flag = false;
    for(int i = a; i <= b; i++) {
        if(i % k == 0) flag = true;
    }
    printf("%s\n", flag ? "OK" : "NG");
    return 0;
}
A.cpp

B - 1%

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int main() {
    ll n, now = 100;
    scanf("%lld", &n);
    int ans = 0;
    while(now < n) {
        now += now / 100;
        ans++;
    }
    printf("%d\n", ans);
    return 0;
}
B.cpp

C - Many Requirements

题意:给Q个四元组{ai,bi,ci,di},要求生成一个长度为N且值在[1,M]之间的不下降序列A,令$S=\sum_{A_{b_{i}}-A_{a_{i}}=c_{i}} d_{i}$,最大化S。

数据范围:$ 2 \leq N \leq 10, 1 \leq M \leq 10,1 \leq Q \leq 50, 1 \leq a_{i} < b_{i} \leq N, 0 \leq c_{i} < M, 1 \leq d_{i} \leq 10^{5} $

题解:暴力求出每个满足要求的序列,然后依次求出S,每次取大即可。暴力求出每个序列的复杂度是$C(n + m - 1, n)$,隔板法。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 55;
int a[N], b[N], c[N], d[N];
int n, m, q, ans;
void dfs(int x, vector<int>& t) {
    if(t.size() == n) {
        int sum = 0;
        for(int i = 0; i < q; i++) {
            if(t[b[i]] - t[a[i]] == c[i]) sum += d[i];
        }
        ans = max(ans, sum);
        return;
    }
    for(int i = x; i <= m; i++) {
        t.push_back(i);
        dfs(i, t);
        t.pop_back();
    }
}
int main() {
    scanf("%d%d%d", &n, &m, &q);
    for(int i = 0; i < q; i++) {
        scanf("%d%d%d%d", &a[i], &b[i], &c[i], &d[i]);
        a[i]--, b[i]--;
    }
    vector<int> t;
    t.push_back(1);
    dfs(1, t);
    printf("%d\n", ans);
    return 0;
}
C.cpp

 D - Floor Function

题意:在[1,N]之间取一个整数x,最大化$ \left \lfloor \frac{Ax}{B} \right \rfloor - A\left \lfloor \frac{x}{B} \right \rfloor $。

数据范围:$ 1 \leq A \leq 10^{6}, 1 \leq B,N \leq 10^{12} $

题解:可以发现这个值是有一个长度为B的循环节,且在[0,B-1]上是递增的,所以答案就是A*min(B - 1, N) / B。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int main() {
    ll a, b, n;
    scanf("%lld%lld%lld", &a, &b, &n);
    printf("%lld\n", a * min(b - 1, n) / b);
    return 0;
}
D.cpp

E - Rotation Matching

题意:输出M对不同数字(ai,bi)[1,N],每一轮编号为ai和bi去第i个地方比赛,比完一轮以后,每个人的编号加1,如果当前这个人编号为N,则变为1,满足N轮以后没有一对人重复比过。

数据范围:$ 1 \leq M , M \times 2 + 1 \leq N \leq 100000 $

题解:题意比较绕,简化了就是输出M对不同的数字(ai,bi),定义dis(x,y)为(x-y+(x - y < 0 ? n : 0)),满足任意i,j,dis(ai,bi) != dis(aj,bj),dis(ai,bi) != dis(bj,aj),dis(bi,ai) != dis(aj,bj),dis(bi,ai) != dis(bj,aj)。

具体构造见代码。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int main() {
    int n, m;
    scanf("%d%d", &n, &m);
    if(n & 1) {
        for(int i = 0; i < m; i++) {
            printf("%d %d\n", i + 1, n - i - 1);
        }
    }else {
        for(int i = 0; i < m; i++) {
            if(i < n / 4) printf("%d %d\n", i + 1, n - i);
            else printf("%d %d\n", i + 1, n - i - 1);
        }
    }
    return 0;
}
E.cpp

F - LIS on Tree

题意:给一颗N个节点的树,每个节点有个值ai,求1到其它节点的最短路径中a构造的最长上升子序列。

数据范围:$ 2 \leq N \leq 2 \times 10^{5} , 1 \leq a_{i} \leq 10^{9} $

题解:一般的最长上升子序列可以用二分一个升序序列更新可求得,这题以1为根节点dfs,二分更新序列,递归下去,然后回溯即可。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 2e5 + 5;
vector<int> G[N];
int a[N], ans[N];
void dfs(int u, int fa, vector<int>& t) {
    ans[u] = t.size();
    for(auto v : G[u]) {
        if(v == fa) continue;
        int L = 0, R = t.size() - 1, x = -1;
        while(L <= R) {
            int mid = (L + R) >> 1;
            if(t[mid] >= a[v]) x = mid, R = mid - 1;
            else L = mid + 1;
        }
        int tmp;
        if(x == -1) t.push_back(a[v]);
        else tmp = t[x], t[x] = a[v];
        dfs(v, u, t);
        if(x == -1) t.pop_back();
        else t[x] = tmp;
    }
}
int main() {
    int n;
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
    }
    for(int i = 1, u, v; i < n; i++) {
        scanf("%d%d", &u, &v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
    vector<int> t;
    t.push_back(a[1]);
    dfs(1, -1, t);
    for(int i = 1; i <= n; i++) {
        printf("%d\n", ans[i]);
    }
    return 0;
}
F.cpp

 

posted @ 2020-05-03 12:37  zdragon  阅读(195)  评论(0编辑  收藏  举报