题目链接

A 完美数

签到题,不要循环,记得开ll。

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 100010;

int main()
{
    long long n;
    cin>>n;
    cout<<n/2520<<endl;
    return 0;
}

B 最大价值

这个题是一个完全背包加多重背包的题,先对重量为0的物品做一遍完全背包,在对剩下的物品做一次多重背包即可。

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 1010;

int f[N];
int n, m, v, w;

int main() {
    cin >> n >> m >> v >> w;
    for (int i = v; i <= n; i++)f[i] = max(f[i], f[i - v] + w);

    int l, h;
    for (int i = 1; i <= m; i++) {
        cin >> l >> h >> v >> w;
        for (int j = n; j >= v; j--) {
            for (int k = 0; k * h <= l && k * v <= j; k++) {
                f[j] = max(f[j], f[j - k * v] + k * w);
            }
        }
    }
    cout << f[n] << endl;
    return 0;
}

借鉴了其他人的题解发现也可以把所有物品重新打包,因为无限去也不能无限取,背包的容量有限制,重新打包对每一份物品取还是不取,从而转化为一个01背包的问题。

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

const int N = 100010, M = 1010;

int v[N], w[N], f[N][M];
int n, m, v0, w0;

int main() {
    cin >> n >> m >> v0 >> w0;
    int q = n / v0;
    int t = 1;
    while (q--)v[t] = v0, w[t] = w0, t++;
    while (m--) {
        int l, h, v1, w1;
        cin >> l >> h >> v1 >> w1;
        q = l / h;
        while (q--)v[t] = v1, w[t] = w1, t++;
    }
    for (int i = 1; i < t; i++) {
        for (int j = 0; j <= n; j++) {
            f[i][j] = f[i - 1][j];
            if (j >= v[i])f[i][j] = max(f[i][j], f[i - 1][j - v[i]] + w[i]);
        }
    }
    cout << f[t - 1][n] << endl;
    return 0;
}

C 维护数组

这是一题典型的动态求一段区间的和的题目,可以用树状数组来做,可以将整段区间分为前后两个数组,分别对两个树状数组求和即可,最后再把两个加起来就是答案,但唯一要注意的是每次修改某个数的值要和给定的值取min。

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

const int N = 200010;

int tr1[N], tr2[N];
int  s[N];
int n, k, a, b, q;

int lowbit(int x) {
    return x & (-x);
}

void add(int tr[],int x,int y) {
    for (int i = x; i <= n; i += lowbit(i))
        tr[i] += y;
}

int query(int tr[],int x) {
    int res = 0;
    for (int i = x; i; i -= lowbit(i))
        res += tr[i];
    return res;
}

int main() {
    cin >> n >> k >> a >> b >> q;
    while (q--) {
        int op;
        cin >> op;
        if (op == 1) {
            int x, y;
            cin >> x >> y;
            add(tr1, x, min(s[x] + y, b) - min(s[x], b));
            add(tr2, x, min(s[x] + y, a) - min(s[x], a));
            s[x] += y;
        } else {
            int p;
            cin >> p;
            cout << query(tr1, p - 1) + query(tr2, n) - query(tr2, p + k - 1) << endl;
        }
    }
}