2023.6.17 每日一题

原题链接

A: Codeforces Round 572 (Div. 1) - C

B: Codeforces Round 691 (Div. 1) - A

A. Array Beauty - 2500

题目大意

定义一个数组 \(a\) 的美丽值为 :

\[\min_{1\le i<j\le n} |a_i - a_j| \]

现在要求长度为 \(k\) 的所有子序列的美丽值之和。

解题思路

参考了dyh大爹的代码

首先鉴于一个子序列的美丽值的上界一定是 \(\frac{\max{a_i}}{k - 1}\),我们可以直接枚举每一种可能的美丽值,然后去找这种美丽值在多少子序列中出现。那么我们处理大于枚举值的子序列种类数,使用dp和一个前缀和数组表示,转移方程是从上一个选择的数迁移到新的数,使用一个双指针优化。每次枚举完成后将结果统计起来就可以得到答案了。

AC Code

#include <iostream>
#include <algorithm>
#include <cstring>
#include <numeric>
#define endl '\n'
#define ios ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)
using namespace std;
typedef long long LL;

const int N = 1010;
const int MOD = 998244353;

int a[N];
LL dp[N][N], s[N][N];

void solve() {
    LL res = 0;
    int n, k;
    cin >> n >> k;
    for (int i = 1; i <= n; ++i) {
        cin >> a[i];
    }
    sort(a + 1, a + n + 1);
    for (int i = 1; i <= (100010) / (k - 1); ++i) {
        for (int j = 1; j <= n + 1; ++j) {
            for (int l = 1; l <= k + 1; ++l) {
                dp[j][l] = 0;
                s[j][l] = 0;
            }
        }
        int cnt = 1;
        dp[1][1] = s[1][1] = 1;
        for (int j = 2; j <= n + 1; ++j) {
            while (cnt + 1 < j && a[j - 1] - a[cnt] >= i) cnt++;
            for (int l = 2; l <= k + 1; ++l) {
                dp[j][l] = s[cnt][l - 1];
            }
            for (int l = 1; l <= k + 1; ++l) {
                s[j][l] = (dp[j][l] + s[j - 1][l]) % MOD;
            }
        }
        res = (res + s[n + 1][k + 1]) % MOD;
    }
    cout << res << endl;
}

signed main() {
    ios;
    int T = 1;
//    cin >> T;
    while (T--) {
        solve();
    }
}



B. Row GCD - 1600

题目大意

给定两列大正数 \(a_1,\dots, a_n\)\(b_1,\dots,b_m\),现在要求 \(a_1 + b_j, \dots, a_n + b_j\) 的最大公约数。

解题思路

暴力一个个找不TLE才怪了,我们需要找到每次运算的公共特征。

我们知道对于gcd有如下性质:

\[\gcd(a,\ b) = \gcd(a,\ b - a) \]

这是我们欧几里得算法成立的重要条件。

那么对我们求的式子处理,就得到:

\[\begin{aligned} &\gcd(a_1 + b_j,\ a_2 + b_j,\dots,\ a_n + b_j)\\ =&\gcd(a_1 + b_j,\ a_2 - a_1,\dots,\ a_n - a_1)\\ =&\gcd(a_1 + b_j, gcd\_) \end{aligned} \]

这里的 \(gcd\_\) 是恒定值,可以在读入 \(a\) 数列时得到,那么只需要保留一个 \(a_1\) 的值,其他值在读入时优化掉即可。

AC Code

#include <iostream>
#include <algorithm>
#include <cstring>
#include <numeric>
#define endl '\n'
#define ios ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)
using namespace std;
typedef long long LL;

const int N = 3e5 + 10;
const int MOD = 1e9 + 7;

void solve() {
    int n, m;
    cin >> n >> m;
    n--;
    LL a;
    cin >> a;
    LL gcd_ = 0;
    while (n--) {
        LL x;
        cin >> x;
        gcd_ = gcd(gcd_, x - a);
    }
    gcd_ = abs(gcd_);
    while (m--) {
        LL x;
        cin >> x;
        cout << gcd(gcd_, a + x) << ' ';
    }
    cout << endl;
}

signed main() {
    ios;
    int T = 1;
//    cin >> T;
    while (T--) {
        solve();
    }
}
posted @ 2023-06-17 11:27  叁纔  阅读(17)  评论(0编辑  收藏  举报