百度之星 (2022-09-10)

发布于 2022-09-09 16:00 744 字 4 min read 手写 每个字都是我自己敲的。

Zhiheng Wang avatar

Zhiheng Wang

技术文章、个人随笔、项目与作品体验记录

百度之星复赛,记一下这两题。 A. 子序列 比赛题目入口 把数组分成若干个非空递增子序列,求最大的总得分。 每个数单独放成一个子序列就能取到上界,答案直接是数组元素之和。读入后累加,注意总和用 。 C. 最大值 题目链接 长度为 $n$ 的数组,每个数都在 $[1,m]$ 内。一个数组的权值是等于最大值的元素个数,求所有数组的权值之和,对 $998244353$ 取模。保证...

2022 百度之星复赛,记一下这两题。

A. 子序列

比赛题目入口

题意

把数组分成若干个非空递增子序列,求最大的总得分。

思路

每个数单独放成一个子序列就能取到上界,答案直接是数组元素之和。读入后累加,注意总和用 long long。

代码

#include <bits/stdc++.h>
using namespace std;

#define mp make_pair
#define pb push_back
#define fi first
#define se second

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


void debug(int x) {
    printf("??? %d\n", x);
}

void debug(int *X, int x) {
    printf("??? ");
    for(int i = 1; i <= x; i++) printf("%d%c", X[i], " \n"[i == x]);
}

ll ans;

void solve() {
    int x;
    scanf("%d", &x);
    ans += x;
}

int main() {
    int T;
    // T = 1;
    scanf("%d", &T);
    // cin >> T;
    while(T--) {
        solve();
    }
    printf("%lld\n", ans);
    return 0;
}

C. 最大值

题目链接

题意

长度为 nn 的数组,每个数都在 [1,m][1,m] 内。一个数组的权值是等于最大值的元素个数,求所有数组的权值之和,对 998244353998244353 取模。保证 nm≤1012nm\le10^{12}。

思路

固定一个位置,假设它的值是 xx,并且它是最大值,那么其他位置都可以从 11 到 xx 随便选,共 xn−1x^{n-1} 种。每个位置的贡献一样,所以答案是

n∑x=1mxn−1.n\sum_{x=1}^{m}x^{n-1}.

n,mn,m 至少有一个不超过 10610^6。mm 小就直接快速幂求和;否则 nn 小,幂和是 nn 次多项式,算出 00 到 nn 的值后做拉格朗日插值。

代码

#include <bits/stdc++.h>
using namespace std;

#define mp make_pair
#define pb push_back
#define fi first
#define se second

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

const ll mo = 998244353;

inline ll fpow(ll x, ll y) {
    ll res = 1; for(; y; y >>= 1, x = x * x % mo) if(y & 1) res = res * x % mo; return res;
}

void debug(int x) {
    printf("??? %d\n", x);
}

void debug(int *X, int x) {
    printf("??? ");
    for(int i = 1; i <= x; i++) printf("%d%c", X[i], " \n"[i == x]);
}

ll n, m, ans;

void solve() {
    // cout << fpow(4, 3) << endl;
    cin >> n >> m;
    ans = 0;
    if(m <= n) {
        for(ll i = 1; i <= m; i++) ans = (ans + fpow(i, n - 1)) % mo;
    }
    else {
        int k = n;
        vector<ll> y(k + 1), fac(k + 1), pre(k + 2), suf(k + 2);
        for(int i = 1; i <= k; i++) y[i] = (y[i - 1] + fpow(i, n - 1)) % mo;
        ll x = m % mo;
        if(x <= k) ans = y[x];
        else {
            fac[0] = 1;
            for(int i = 1; i <= k; i++) fac[i] = fac[i - 1] * i % mo;
            fac[k] = fpow(fac[k], mo - 2);
            for(int i = k; i >= 1; i--) fac[i - 1] = fac[i] * i % mo;
            pre[0] = suf[k + 1] = 1;
            for(int i = 0; i <= k; i++) pre[i + 1] = pre[i] * (x - i + mo) % mo;
            for(int i = k; i >= 0; i--) suf[i] = suf[i + 1] * (x - i + mo) % mo;
            for(int i = 0; i <= k; i++) {
                ll tmp = y[i] * pre[i] % mo * suf[i + 1] % mo;
                tmp = tmp * fac[i] % mo * fac[k - i] % mo;
                if((k - i) & 1) ans = (ans - tmp + mo) % mo;
                else ans = (ans + tmp) % mo;
            }
        }
    }
    ans = ans * (n % mo) % mo;
    cout << ans << endl;
}

int main() {
    int T;
    T = 1;
    // scanf("%d", &T);
    // cin >> T;
    while(T--) {
        solve();
    }
    return 0;
}

执笔 手写

随机文章

© 2026 Zhiheng Wang @traceonsnow
Powered by theme astro-koharu · Inspired by Shoka
加载中...