The 18th Heilongjiang Provincial Collegiate Programming Contest

A. Magic Computer

看题目猜规律

#include <bits/stdc++.h>

using namespace std;

#define int long long
using vi = vector<int>;
using i32 = int32_t;

const int mod = 998244353;

int power(int x, int y) {
    int ans = 1;
    while (y) {
        if (y & 1) ans = ans * x % mod;
        x = x * x % mod, y /= 2;
    }
    return ans;
}

i32 main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    int k;
    cin >> k, k -= 1;
    cout << power( 2 , k ) << "\n";
    return 0;
}

E. Ethernet

数据范围有限,可以直接用dfs统计出所有的情况,然后计算概率即可

#include <bits/stdc++.h>

using namespace std;

using i32 = int32_t;
using i64 = long long;
int n, m;
double ans;

void dfs(int u, double p, vector<int> a) {
    if (u == n) {
        ans += p;
        return;
    }
    if (u <= m) {
        double cnt = .0;
        for (int i = 1; i <= n; i++) {
            if (!a[i]) {
                cnt += 1.0;
            }
        }
        for (int i = 1; i < n; i++) {
            if (!a[i]) {
                a[i] = u;
                dfs(u + 1, p * (1.0 / cnt), a);
                a[i] = 0;
            }
        }
    } else {
        if (a[u] == 0) {
            a[u] = u;
            dfs(u + 1, p, a);
        } else {
            double cnt = .0;
            for (int i = 1; i <= n; i++) {
                if (!a[i]) {
                    cnt += 1.0;
                }
            }
            for (int i = 1; i < n; i++) {
                if (!a[i]) {
                    a[i] = u;
                    dfs(u + 1, p * (1.0 / cnt), a);
                    a[i] = 0;
                }
            }
        }
    }
}


i32 main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    cin >> n >> m;
    vector<int> a(n + 1);
    dfs(1, 1.0, a);
    cout << fixed << setprecision(10) << ans << endl;
    return 0;
}

F. Folder

直接统计一下子节点的种类即可

#include<bits/stdc++.h>

using namespace std;
#define int long long
#define double long double

signed main() {
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int n;
    cin >> n;
    int ans = 0;
    vector<int> ve(n + 5);
    for (int i = 2; i <= n; ++i) {
        int x;
        cin >> x;
        if (ve[x])ans++;
        ve[x]++;
    }
    cout << ans;
    return 0;
}

I. Club

有两类勋章

第一类\(a\)种勋章,每种勋章\(x\)个活动

第二类\(b\)种勋章,每种勋章\(y\)个活动

\(f_{i,j}\)表示差\(i\)种第一类勋章和\(j\)种第二类勋章所需要的期望次数,因此\(f_{0,0} =0\)

对于枚举到的状态\(f_{i,j}\),选到一种新的概率\(p=\frac{ix + jy}{n}\),期望次数\(E=\frac 1p\)。其中选到第一类的概率是\(\frac{ix}{ix+jy}\),选到第二类的概率是\(\frac{jy}{ix+jy}\),所以

\[f_{i,j} = \frac{ix}{ix+jy} f_{i-1,j} + \frac{jy}{ix+jy} f_{i,j-1} + \frac{n}{ix+jy} \]

#include <bits/stdc++.h>

using namespace std;

#define int long long
using vi = vector<int>;
using i32 = int32_t;
using ldb = long double;

const int mod = 998244353;
#define DEBUG(x) cerr <<(#x) << " = " << x  << "\n";

i32 main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    int n, m;
    cin >> n >> m;
    int x = n / m, y = x + 1;
    int a = m + m * x - n, b = m - a;
    auto f = vector(a + 1, vector<double>(b + 1));
    for (int k = 1, ix, jy, t; k <= m; k++) {
        for (int i = 0, j = k; i <= k; i++, j--) {
            if (i > a or j > b) continue;
            ix = i * x, jy = j * y, t = ix + jy;
            f[i][j] = ldb(n) / t;
            if (i > 0) f[i][j] += ix * f[i - 1][j] / t;
            if (j > 0) f[i][j] += jy * f[i][j - 1] / t;
        }
    }
    cout << fixed << setprecision(10) << f[a][b] << "\n";
    return 0;
}
posted @ 2024-02-10 18:27  PHarr  阅读(214)  评论(0编辑  收藏  举报