第十六程协杯程序设计竞赛

A - 营救普雷赛斯

#include <bits/stdc++.h>

using namespace std;

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

const int inf = 1e10, INF = 1e18;
const int mod = 998244353;

const int N = 1e6;

i32 main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    int n;
    cin >> n;
    vi a(n), b(n), vis(n);
    for (auto &i: a) cin >> i;
    for (auto &i: b) cin >> i;
    for (int i = 0, day = 1;; day++) {
        if (vis[i]) break;
        vis[i] = 1;
        i = i + a[i];
        if (i >= n) {
            cout << day << "\n";
            return 0;
        }
        i = max(0ll, i - b[i]);
    }
    cout << "-1\n";
    return 0;
}

B - 让德克萨斯担任队长

答案是\(\sum_{i=\frac n 2 } ^ n C_n{i}\times(i-1)!\times(n-i)!\)

具体的操作思路是每一个人都选择直接的自己编号的盒子,然后如果不是,就继续选择盒子里面的里面对应的数字。所以不合法的情况,只有当虚拟中出现一个大于$\frac n 2 $的环的。

#include <bits/stdc++.h>

using namespace std;

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

const int inf = 1e10, INF = 1e18;

const int N = 4e5 + 5;
const int mod = 1000000007;

int fact[N];
int infact[N];

int qpow(int a, int b) {
    int ans = 1, base = a;
    while (b) {
        if (b & 1) ans = ans * base % mod;
        base = base * base % mod;
        b >>= 1;
    }
    return ans % mod;
}//快速幂模板
void init() {
    fact[0] = 1;
    infact[0] = 1;
    for (int i = 1; i < N; i++) {
        fact[i] = (fact[i - 1] * i) % mod;
    }
    infact[N - 1] = qpow(fact[N - 1], mod - 2);
    for (int i = N - 2; i; i--) {
        infact[i] = infact[i + 1] * (i + 1) % mod;
    }
}//在使用组合数前调用init函数初始化组合数
int C(int a, int b) {
    return (fact[a] * (infact[b] * infact[a - b] % mod)) % mod;
}//预处理阶乘,逆元求组合数

void solve() {
    int n;
    cin >> n;
    int res = 0;
    for (int i = n / 2 + 1; i <= n; i++)
        res = (res + C(n, i) * fact[i - 1] % mod * fact[n - i] % mod) % mod;
    cout << res << "\n";
}

i32 main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    init();
    int TC;
    for (cin >> TC; TC; TC--)
        solve();
    return 0;
}

C - 简单的签到

#include <bits/stdc++.h>

using namespace std;

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

const int inf = 1e10, INF = 1e18;
const int mod = 998244353;

const int N = 1e6;

i32 main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    int n;
    string s;
    cin >> n >> s;
    int x;
    cin >> x;
    int res = 0;
    for( auto i : s ){
        if( i - '0' == x ) res ++;
    }
    cout << res << "\n";
    return 0;
}

D - 安洁莉娜的能量计算

首先\(x!\)的倍数一定是\(k\times x!\),其次\((a_i+1)\times a_1 !=(a_i+1)!\)。所以我们判断一下是否可以把所有的阶乘合并成\(k\times x!\)的形式即可。

#include <bits/stdc++.h>

using namespace std;

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

const int inf = 1e10, INF = 1e18;
const int mod = 998244353;

const int N = 1e6;

i32 main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    int n, T;
    cin >> n >> T;
    vi a(T+1);
    for( int x ; n ; n -- ){
        cin >> x;
        a[x] ++;
    }
    for( int i = 1 ; i < T ; i ++ ){
        if( a[i] % ( i + 1 ) == 0 ) a[i+1] += a[i] / (i+1);
        else {
            cout << "NO\n";
            return 0;
        }
    }
    cout << "YES\n";
    return 0;
}

E - 保护缪缪

用数电里面类似校验码的做法,对于每一个二进制位用一个分身去验证一下,所以代价就是二进制的长度。

#include <bits/stdc++.h>

using namespace std;

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

const int inf = 1e10, INF = 1e18;
const int mod = 998244353;

const int N = 1e6;

void solve() {
    int n, m;
    cin >> n >> m;
    if (n == 1) {
        cout << "0\n";
        return;
    }
    for (int i = 0;; i++) {
        if ((1ll << i) < n) continue;
        cout << i * m << "\n";
        return;
    }
    return;
}

i32 main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    int TC;
    for (cin >> TC; TC; TC--)
        solve();
    return 0;
}

F - 我不是可汗

直接dp就好了

#include <bits/stdc++.h>

using namespace std;

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

const int inf = 1e10, INF = 1e18;
const int mod = 998244353;

const int N = 1e6;

i32 main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    int m, n;
    cin >> m >> n;
    vi v(n + 1), w(n + 1);
    string s;
    for (int i = 1; i <= n; i++)
        cin >> s >> v[i] >> w[i];
    vi f(m + 1);
    for (int i = 1; i <= n; i++) {
        for( int j = m ; j >= v[i] ; j -- )
            f[j] = max( f[j] , f[j - v[i]] + w[i] );
    }
    cout << *max_element(f.begin(), f.end()) << "\n";
    return 0;
}
posted @ 2023-11-20 13:24  PHarr  阅读(17)  评论(0编辑  收藏  举报