Codeforces Round#697(Div.3)补题

题目链接:http://codeforces.com/contest/1475/problem/D

题目大意为有n个app,每个app会占用ai的内存,以及具有bi的重要性。求卸载的app内存至少为m以上,同时重要性最小。

这道题第一眼看上去应该就是重要性为1的app的数量要尽可能多,同时重要性为2的app的数量要尽可能少。

第二步就是重要性为1且内存大的app数量要尽可能多,重要性为2且内存大的app数量要尽可能多。

为此,我们需要对重要性为1和2的内存进行降序排列。

先计算重要性为2的全部内存之和,并在此基础之上减去重要性2的内存加上重要性为1的内存,同时进行重要性的比较取最小值。

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 typedef long long ll;
 5 const int INF = 0x3f3f3f3f;
 6 const int N = 2e5 + 10;
 7 
 8 void solve()
 9 {
10     int n, m;
11     cin >> n >> m;
12     vector<int> a, b;
13     vector<int> v;
14     for (int i = 0; i < n; i++) {
15         int e;
16         cin >> e;
17         v.push_back(e);
18     }
19     for (int i = 0; i < n; i++) {
20         int e;
21         cin >> e;
22         if (e == 1) {
23             a.push_back(v[i]);
24         }
25         else {
26             b.push_back(v[i]);
27         }
28     }
29     sort(a.rbegin(), a.rend());
30     sort(b.rbegin(), b.rend());
31     ll sumb = accumulate(b.begin(), b.end(), 0ll);
32     ll suma = 0;
33     int r = b.size();
34     int ans = INF;
35     for (int i = 0; i <= a.size(); i++) {
36         while (r > 0 && suma + sumb - b[r - 1] >= m) {
37             r--;
38             sumb -= b[r];
39         }
40         if (suma + sumb >= m) {
41             ans = min(ans, 2 * r + i);
42         }
43         if (i != a.size()) {
44             suma += a[i];
45         }
46     }
47     cout << (ans == INF ? -1 : ans) << endl;
48 }
49 
50 int main()
51 {
52     int t;
53     cin >> t;
54     while (t--) {
55         solve();
56     }
57 }

 题目链接:http://codeforces.com/contest/1475/problem/E

题目大意:n个人,每个人都有ai个粉丝。现在要从中选出k个人使他们的粉丝数最多。求选的方案数。

很简单的一道题,只需要统计出粉丝数相同的有几个人,再按粉丝数从大到小排序,如果粉丝数相同的人的数量比k小,就遍历下一个粉丝数比它小的,同时k要减去该粉丝数相同的人数。如果比k大就粉丝数相同的人数里面选出k个人。

#include <bits/stdc++.h>
 
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int N = 1e3 + 10;
const int mod = 1e9 + 7;
 
int c[N][N];
 
void init()
{
    for (int i = 0; i <= 1e3; i++) {
        c[i][i] = 1;
        c[i][0] = 1;
    }
    for (int i = 1; i <= 1e3; i++) {
        for (int j = 1; j <= 1e3; j++) {
            c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;
        }
    }
}
 
void solve()
{
    int n, k;
    cin >> n >> k;
    map<int,int> m;
    vector<int> v;
    for (int i = 0; i < n; i++) {
        int x;
        cin >> x;
        if (!m[x]) {
            v.push_back(x);
        }
        m[x]++;
    }
    //cout << v.size() << endl;
    sort(v.rbegin(), v.rend());
    ll ans = 1;
    for (int i = 0; i < v.size(); i++) {
        if (m[v[i]] < k) {
            k -= m[v[i]];
        }
        else {
            ans *= c[m[v[i]]][k] % mod;
            break;
        }
    }
    cout << ans << endl;
}
 
int main()
{
    init();
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
}

  题目链接:http://codeforces.com/contest/1475/problem/F

题目大意:给定两个01矩阵,问是否能从第一个矩阵变为第二个矩阵。操作为:把某一列的所有元素都与1异或或者把每一行都与1异或。因此只需要按列模拟一遍,再按行模拟一遍。

#include <bits/stdc++.h>
 
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int N = 1e3 + 10;
const int mod = 1e9 + 7;
 
 
 
void solve()
{
    int n;
    cin >> n;
    string s = "";
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            char x;
            cin >> x;
            s += x;
        }
    }
    char c = getchar();
    string s1 = "";
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            char x;
            cin >> x;
            s1 += x;
        }
    }
    for (int i = 0; i < n; i++) {
        if (s[i] != s1[i]) {
            for (int j = i; j < n*n; j += n) {
                if (s[j] == '0') {
                    s[j] = '1';
                }
                else {
                    s[j] = '0';
                }
            }
        }
    }
    for (int i = n; i < n * n; i += n) {
        if (s[i] != s1[i]) {
            for (int j = i; j < i+n; j++) {
                if (s[j] == '0') {
                    s[j] = '1';
                }
                else {
                    s[j] = '0';
                }
            }
        }
    }
    if (s == s1) {
        cout << "Yes" << endl;
    }
    else {
        cout << "No" << endl;
    }
}
 
int main()
{
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
}

  题目链接:http://codeforces.com/contest/1475/problem/G

题目大意,给n个数,求要使两两可以相除要移除的最小元素数量。其实就是求可以两两相除的最大元素个数。

这道题。。。一个sort排序卡了我半天,最后看题解只需要从1筛到2e5就可以。。。

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int N = 2e5 + 10;
const int mod = 1e9 + 7;

int a[N], dp[N];

void solve()
{
    int n;
    cin >> n;
    memset(a, 0, sizeof(a));
    memset(dp, 0, sizeof(dp));
    for (int i = 0; i < n; i++) {
        int x;
        cin >> x;
        a[x]++;
    }
    int ans = -INF;
    for (int i = 1; i <N; i++) {
        if (a[i]) {
            dp[i] += a[i];
            for (int j = i + i; j <= N; j += i) {
                dp[j] = max(dp[i], dp[j]);
            }
        }
        ans = max(dp[i], ans);
    }
    cout << n - ans << endl;
}

int main()
{
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
}

  

原文地址:https://www.cnblogs.com/Drqidian/p/14332847.html