列表

详情


NC223203. D 小 L 与 GCD

描述

给定一个正整数序列 . 定义子序列为该序列按序保留若干项(非空) 后构成的序列,例如对于序列 等都是其子序列。

定义一个子序列的权值为序列内所有数的最大公因数,请求出权值前 k 大的子序列(若权值相同,按选取下标的字典序从小到大排列)。特别地,由于输出量可能过大, 你只需要输出这这些子序列中每个子序列选取下标乘积的和即可。对 取模。

输入描述

第一行两个数 .

接下来一行 n 个数,第 i 个数为数列 .

输出描述

输出一个数,表示 GCD 前 k 大的子序列选取下标乘积的和。若不存在前 k 大的子序列,输出 -1.

示例1

输入:

20 10000
18 12 16 20 8 20 2 12 20 2 14 20 14 16 12 8 20 16 14 20

输出:

2840199644

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 43ms, 内存消耗: 1172K, 提交时间: 2021-09-20 19:35:22

#include<bits/stdc++.h>

using namespace std;
const int N = 2e5 + 10;
int a[N], n, k;
vector<int> b;
unsigned ans;

void dfs(int u, int g, int c, unsigned p) {
    if (!k)return;
    if (c == g) ans += p, k--;
    for (int i = u + 1; i < (int) b.size(); i++)
        dfs(i, g, __gcd(c, a[b[i]]), p * b[i]);
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cin >> n >> k;
    for (int i = 1; i <= n; i++)cin >> a[i];
    int mx = *max_element(a + 1, a + 1 + n);
    for (int i = mx; k && i >= 1; i--) {
        b.clear();
        for (int j = 1; j <= n; j++)
            if (a[j] % i == 0)b.push_back(j);
        if (!b.empty())dfs(-1, i, 0, 1);
    }
    if (k)cout << -1 << "\n";
    else cout << ans << "\n";
    return 0;
}

上一题