AtCoder Beginner Contest 163


傳送門

A - Circle Pond

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int main() {
    int n;
    scanf("%d", &n);
    printf("%.6f\n", 2.0 * acos(-1) * n);
    return 0;
}
A.cpp

B - Homework

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

C - management

題意:給一棵N個節點的有根樹,求每個節點的兒子數。

數據范圍:$ 2 \leq N \leq 2 \times 10^{5} $

題解:由於輸入直接給的是每個節點的父節點,直接計數即可。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 2e5 + 5;
int a[N];
int main() {
    int n;
    scanf("%d", &n);
    for(int i = 1, x; i < n; i++) {
        scanf("%d", &x);
        a[x]++;
    }
    for(int i = 1; i <= n; i++) {
        printf("%d\n", a[i]);
    }
    return 0;
}
C.cpp

D - Sum of Large Numbers

題意:當前有N + 1個整數:10100,10100+1,...,10100+N,求取不少於K個數的和的可能值的數量(mod 1e9+7)。

數據范圍:$ 1 \leq N \leq 2 \times 10^{5},1 \leq K \leq N+1 $

題解:10100很大,所以取K個數的總和不可能等於取K+1個數的總和,所以只需要枚舉取多少個數。

對於取K個數,可以求出取K個值的最小最大值,在這兩個值之間的值都可以取到,個數就是最大值-最小值+1。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int MD = 1e9 + 7;
void add(int& x, int y) {
    x += y;
    if(x >= MD) x -= MD;
    if(x < 0) x += MD;
}
int cal(int l, int r) {
    return 1LL * (l + r) * (r - l + 1) / 2 % MD;
}
int main() {
    int n, k, ans = 0;
    scanf("%d%d", &n, &k);
    for(int i = k; i <= n + 1; i++) {
        add(ans, cal(n + 1 - i, n) - cal(0, i - 1) + 1);
    }
    printf("%d\n", ans);
    return 0;
}
D.cpp

 E - Active Infants

題意:有N個小孩,第i個孩子的位置為i,活躍值為Ai,現在將N個小孩重新排列,每個小孩獲得的開心值為Ai與重新排列前后位置差的乘積,求最大可能的開心值總和。

數據范圍:$ 2 \leq N \leq 2000, 1 \leq A_{i} \leq 10^{9} $

題解:可以發現將A較大的值放在邊上更優,以A降序,然后就是一個區間dp,枚舉當前值放左邊、右邊進行更新。

$ f[l][r] = max(f[l+1][r] + A_{now} \times \left |  p_{now} - l \right |,f[l][r-1]+A_{now} \times \left |  p_{now} - r\right | )$

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 2e3 + 5;
ll f[N][N];
pair<int, int> p[N];
ll cal(int cnt, int l, int r) {
    if(l > r) return 0;
    if(~f[l][r]) return f[l][r];
    ll ans = 1LL * p[cnt].first * abs(p[cnt].second - l) + cal(cnt + 1, l + 1, r);
    ans = max(ans, 1LL * p[cnt].first * abs(p[cnt].second - r) + cal(cnt + 1, l, r - 1));
    return f[l][r] = ans;
}
int main() {
    int n;
    scanf("%d", &n);
    for(int i = 1, x; i <= n; i++) {
        scanf("%d", &x);
        p[i] = {x, i};
    }
    sort(p + 1, p + n + 1,[](pair<int, int> a, pair<int, int> b) {
        return a.first > b.first;
    });
    memset(f, -1, sizeof f);
    printf("%lld\n", cal(1, 1, n));
    return 0;
}
E.cpp

 F - path pass i

題意:給一棵N個節點的無根樹,每個節點有一個顏色屬性c,對於每個顏色,求經過這種顏色的簡單路徑的數量。

數據范圍:$ 1 \leq c_{i} \leq N \leq 2 \times 10^{5} $

題解:把問題轉換成不經過這種顏色的簡單路徑的數量,總數f[N] = N*(N+1)/2減去它即可。

其中不經過顏色i的簡單路徑的數量為:$ \sum_{u!=v,u!=w,v!=w,c_{u}=c_{v}=i,\forall \ w \  \epsilon \ path(u,v), c_{w} != i} f[dis(u,v)-1] $。

以任意一點為根節點,遍歷的時候同時更新相應的值,具體看代碼。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 2e5 + 5;
vector<int> G[N];
int C[N], num[N], sum[N];//num[i]代表i子樹的節點數目,sum[i]代表以顏色為i的節點(其祖先沒有顏色為i的節點)為根節點的子樹大小總和
ll ans[N];
ll cal(int x) {
    return 1LL * x * (x + 1) / 2;
}
void dfs(int u, int fa) {
    int c = C[u], save = sum[c];
    num[u] = 1;
    for(auto v : G[u]) {
        if(v == fa) continue;
        int t = sum[c];
        dfs(v, u);
        int dt = sum[c] - t;
        ans[c] -= cal(num[v] - dt);//num[v]-dt代表相鄰兩個節點之間的節點數
        num[u] += num[v];
    }
    sum[c] = save + num[u];
}
int main() {
    int n;
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) {
        scanf("%d", &C[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);
    }
    for(int i = 1; i <= n; i++) {
        ans[i] = cal(n);
    }
    dfs(1, -1);
    for(int i = 1; i <= n; i++) {
        int t = n - sum[i]; //多出來的節點還要減掉
        ans[i] -= cal(t);
        printf("%lld\n", ans[i]);
    }
    return 0;
}
F.cpp

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM