Submission #1328319

#TimeUsernameProblemLanguageResultExecution timeMemory
1328319youssefbyKnapsack (NOI18_knapsack)C++20
37 / 100
1095 ms51444 KiB
// Author: Youssef ben youssef
// Template for Competitive Programming
#include<utility>
#include<map>
#include<unordered_map>
#include<vector>
#include<set>
#include<ios>
#include<iostream>
#include<string>
#include<algorithm>
#include<cmath>
#include <deque>
#include <forward_list>
#include <unordered_set>
#include <stack>
#include <queue>
#include <bitset>
#include <numeric>
#include <iomanip>
using namespace std;
//----------------- Macros -----------------
#define ll long long
#define ull unsigned long long
#define ld long double
#define vi vector<ll>
#define vvi vector<vi>
#define vii vector<pair<ll, ll>>
#define pii pair<ll, ll>
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(v) v.begin(), v.end()
#define endl '\n'
#define fast                 \
    ios::sync_with_stdio(0); \
    cin.tie(0);              \
    cout.tie(0)
#define For(i, a, b) for (int i = (a); i < (b); i++)
#define RevFor(i, a, b) for (int i = (a); i >= (b); i--)
#define set_precision(x) cout << fixed << setprecision(x)



//--------------- Constants ---------------
const ll MOD = 1e9 + 7;
const int MOD2 = 998244353;
const ll INF = 9223372036854775807;
const ll inf = (1e18) + 9;
const ld PI = acos(-1.0);
const ld EPS = 1e-9;
const int MAXN = 2e6 + 5;
const int MAXSIEVE = 1e6 + 5;

//----------- Modular Arithmetic -----------
inline ll add(ll a, ll b, ll mod = MOD) {
    a += b;
    if (a >= mod) a -= mod;
    return a;
}

inline ll sub(ll a, ll b, ll mod = MOD) {
    a -= b;
    if (a < 0) a += mod;
    return a;
}

inline ll mul(ll a, ll b, ll mod = MOD) {
    return (ll)(a * b % mod);
}

ll binpow(ll a, ll b, ll mod = MOD) {
    ll res = 1;
    a %= mod;
    if (a < 0) a += mod;
    while (b) {
        if (b & 1) res = mul(res, a, mod);
        a = mul(a, a, mod);
        b >>= 1;
    }
    return res;
}

inline ll inv(ll a, ll mod = MOD) {
    // assumes mod is prime
    a %= mod;
    if (a < 0) a += mod;
    return binpow(a, mod - 2, mod);
}

inline ll divide(ll a, ll b, ll mod = MOD) {
    return mul(a, inv(b, mod), mod);
}

//------------- Combinatorics --------------
vector<ll> fact(MAXN), inv_fact(MAXN);
void precompute_factorials()
{
    fact[0] = 1;
    For(i, 1, MAXN) fact[i] = mul(fact[i - 1], i);
    inv_fact[MAXN - 1] = inv(fact[MAXN - 1]);
    RevFor(i, MAXN - 2, 0) inv_fact[i] = mul(inv_fact[i + 1], i + 1);
}
int nCr(ll n, ll r)
{
    if (r < 0 || r > n)
        return 0;
    return mul(fact[n], mul(inv_fact[r], inv_fact[n - r]));
}
vector<ll> der(MAXN);

void precompute_derangements() {
    der[0] = 1;
    if (MAXN > 1) der[1] = 0;
    for (int i = 2; i < MAXN; ++i) {
        der[i] = mul(i - 1, add(der[i - 1], der[i - 2]));
    }
}


ll derangement(int n) {
    if (n < (int)der.size()) return der[n];

    ll a = 1;
    ll b = 0;
    for (int i = 2; i <= n; ++i) {
        ll c = mul(i - 1, add(b, a));
        a = b;
        b = c;
    }
    return b;
}


//----------------- Sieve -----------------
vector<int> spf(MAXSIEVE);
vector<bool> is_prime(MAXSIEVE, true);
void sieve()
{
    is_prime[0] = is_prime[1] = false;
    for (int i = 2; i < MAXSIEVE; i++)
    {
        if (is_prime[i])
        {
            spf[i] = i;
            for (int j = i * i; j < MAXSIEVE; j += i)
            {
                if (is_prime[j])
                {
                    is_prime[j] = false;
                    spf[j] = i;
                }
            }
        }
    }
}

//------------- Debugging Helpers ----------
#ifndef ONLINE_JUDGE
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", _debug_print(__VA_ARGS__)
#define debug_container(x) \
    cerr << #x << " = ";   \
    _print_container(x)
#else
#define debug(...)
#define debug_container(x)
#endif

// Primitive types
void _print(int x) { cerr << x; }
void _print(ull x) { cerr << x; }
void _print(ld x) { cerr << x; }
void _print(double x) { cerr << x; }
void _print(char x) { cerr << '\'' << x << '\''; }
void _print(const char* x) { cerr << '\"' << x << '\"'; }
void _print(const string& x) { cerr << '\"' << x << '\"'; }
void _print(bool x) { cerr << (x ? "true" : "false"); }

// STL containers
template <typename T1, typename T2>
void _print(const pair<T1, T2>& p);
template <typename T>
void _print(const vector<T>& x);
template <typename T>
void _print(const deque<T>& x);
template <typename T>
void _print(const forward_list<T>& x);
template <typename T>
void _print(const set<T>& x);
template <typename T>
void _print(const multiset<T>& x);
template <typename T>
void _print(const unordered_set<T>& x);
template <typename T>
void _print(const unordered_multiset<T>& x);
template <typename T1, typename T2>
void _print(const map<T1, T2>& x);
template <typename T1, typename T2>
void _print(const multimap<T1, T2>& x);
template <typename T1, typename T2>
void _print(const unordered_map<T1, T2>& x);
template <typename T1, typename T2>
void _print(const unordered_multimap<T1, T2>& x);
template <typename T>
void _print(const stack<T>& x);
template <typename T>
void _print(const queue<T>& x);
template <typename T>
void _print(const priority_queue<T>& x);
template <typename T, size_t N>
void _print(const array<T, N>& x);
template <typename T, size_t N>
void _print(const T(&x)[N]);

// Policy-based data structures


// Multi-dimensional containers
template <typename T>
void _print(const vector<vector<T>>& x);
template <typename T>
void _print(const vector<vector<vector<T>>>& x);

// Tuple support
template <typename... Args>
void _print(const tuple<Args...>& t);

// Bitset
template <size_t N>
void _print(const bitset<N>& b);

// Custom types (example for DSU and SegmentTree)
struct DSU;
void _print(const DSU& dsu);
struct SegmentTree;
void _print(const SegmentTree& st);

// Implementation of print functions
template <typename T1, typename T2>
void _print(const pair<T1, T2>& p)
{
    cerr << '{';
    _print(p.first);
    cerr << ',';
    _print(p.second);
    cerr << '}';
}

template <typename T>
void _print_container(const T& x)
{
    cerr << '[';
    for (auto it = begin(x); it != end(x);)
    {
        _print(*it);
        if (++it != end(x))
            cerr << ", ";
    }
    cerr << ']';
}

template <typename T>
void _print(const vector<T>& x) { _print_container(x); }

template <typename T>
void _print(const deque<T>& x) { _print_container(x); }

template <typename T>
void _print(const forward_list<T>& x) { _print_container(x); }

template <typename T>
void _print(const set<T>& x) { _print_container(x); }

template <typename T>
void _print(const multiset<T>& x) { _print_container(x); }

template <typename T>
void _print(const unordered_set<T>& x) { _print_container(x); }

template <typename T>
void _print(const unordered_multiset<T>& x) { _print_container(x); }

template <typename T1, typename T2>
void _print(const map<T1, T2>& x)
{
    cerr << '{';
    for (auto it = begin(x); it != end(x);)
    {
        cerr << '{';
        _print(it->first);
        cerr << ':';
        _print(it->second);
        cerr << '}';
        if (++it != end(x))
            cerr << ", ";
    }
    cerr << '}';
}

template <typename T1, typename T2>
void _print(const unordered_map<T1, T2>& x)
{
    cerr << '{';
    for (auto it = begin(x); it != end(x);)
    {
        cerr << '{';
        _print(it->first);
        cerr << ':';
        _print(it->second);
        cerr << '}';
        if (++it != end(x))
            cerr << ", ";
    }
    cerr << '}';
}

template <typename T>
void _print(const stack<T>& x)
{
    stack<T> temp = x;
    vector<T> elements;
    while (!temp.empty())
    {
        elements.push_back(temp.top());
        temp.pop();
    }
    reverse(all(elements));
    _print(elements);
}

template <typename T>
void _print(const queue<T>& x)
{
    queue<T> temp = x;
    vector<T> elements;
    while (!temp.empty())
    {
        elements.push_back(temp.front());
        temp.pop();
    }
    _print(elements);
}

template <typename T>
void _print(const priority_queue<T>& pq)
{
    priority_queue<T> temp = pq;
    vector<T> elements;

    while (!temp.empty())
    {
        elements.push_back(temp.top());
        temp.pop();
    }

    cerr << "max-heap[";
    for (size_t i = 0; i < elements.size(); ++i)
    {
        if (i != 0)
            cerr << " > ";
        _print(elements[i]);
    }
    cerr << "]";
}

// For min-heap (priority_queue with greater<T>)
template <typename T, typename Container>
void _print(const priority_queue<T, Container, greater<T>>& pq)
{
    priority_queue<T, Container, greater<T>> temp = pq;
    vector<T> elements;

    while (!temp.empty())
    {
        elements.push_back(temp.top());
        temp.pop();
    }

    cerr << "min-heap[";
    for (size_t i = 0; i < elements.size(); ++i)
    {
        if (i != 0)
            cerr << " < ";
        _print(elements[i]);
    }
    cerr << "]";
}

// For custom comparators
template <typename T, typename Container, typename Compare>
void _print(const priority_queue<T, Container, Compare>& pq)
{
    priority_queue<T, Container, Compare> temp = pq;
    vector<T> elements;

    while (!temp.empty())
    {
        elements.push_back(temp.top());
        temp.pop();
    }

    cerr << "custom-pq[";
    for (size_t i = 0; i < elements.size(); ++i)
    {
        if (i != 0)
            cerr << " | ";
        _print(elements[i]);
    }
    cerr << "]";
}

template <typename T, size_t N>
void _print(const array<T, N>& x) { _print_container(x); }

template <typename T, size_t N>
void _print(const T(&x)[N]) { _print_container(x); }


template <typename T>
void _print(const vector<vector<T>>& x)
{
    cerr << "[\n";
    for (const auto& v : x)
    {
        cerr << "  ";
        _print(v);
        cerr << "\n";
    }
    cerr << ']';
}

template <typename T>
void _print(const vector<vector<vector<T>>>& x)
{
    cerr << "[\n";
    for (const auto& vv : x)
    {
        cerr << "  ";
        _print(vv);
        cerr << "\n";
    }
    cerr << ']';
}

template <size_t I = 0, typename... Args>
typename enable_if<I == sizeof...(Args), void>::type
_print_tuple(const tuple<Args...>&) {}

// Recursive case - prints current element and recurses
template <size_t I = 0, typename... Args>
typename enable_if < I<sizeof...(Args), void>::type
    _print_tuple(const tuple<Args...>& t)
{
    if (I != 0)
        cerr << ",";        // Print comma separator except before first element
    _print(get<I>(t));      // Print current element
    _print_tuple<I + 1>(t); // Recurse to next element
}

// Main tuple printer
template <typename... Args>
void _print(const tuple<Args...>& t)
{
    cerr << '{';
    _print_tuple(t);
    cerr << '}';
}
template <size_t N>
void _print(const bitset<N>& b)
{
    cerr << b;
}

// Debug print for multiple arguments
void _debug_print() { cerr << endl; }

template <typename T, typename... Args>
void _debug_print(const T& first, const Args &...rest)
{
    _print(first);
    if (sizeof...(rest))
        cerr << ", ";
    _debug_print(rest...);
}
//-------------- Utilities ----------------
template <typename T>
void read(vector<T>& v)
{
    for (auto& x : v)
        cin >> x;
}
template <typename T>
void print(const T& x) { cout << x << endl; }
template <typename T, typename... Args>
void print(const T& first, const Args &...rest)
{
    cout << first << " ";
    print(rest...);
}
template <typename T>
void print_container(const T& container)
{
    for (const auto& x : container)
        cout << x << " ";
    cout << endl;
}
int ceil(int a, int b) { return (a + b - 1) / b; }
int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
int lcm(int a, int b) { return a / gcd(a, b) * b; }

//---------- Essential Data Structures --------

// carefull: Use 0-indexed DSU with size n; for 1-based index, use DSU(n+1)
struct DSU
{
    vi parent, size;

    // Initialize with n elements
    DSU(int n) : parent(n), size(n, 1)
    {
        iota(all(parent), 0);
    }

    // Find with path compression
    int find(int u)
    {
        return parent[u] == u ? u : parent[u] = find(parent[u]);
    }

    // Union by size with success/failure return
    bool unite(int u, int v)
    {
        u = find(u), v = find(v);
        if (u == v)
            return false; // Already in same set

        if (size[u] < size[v])
            swap(u, v); // Union by size
        parent[v] = u;
        size[u] += size[v];
        return true;
    }

    // Check if two elements are in same set
    bool same_set(int u, int v)
    {
        return find(u) == find(v);
    }

    // Get size of the set containing u
    int set_size(int u)
    {
        return size[find(u)];
    }

    // Reset the DSU (useful for multiple test cases)
    void reset()
    {
        iota(all(parent), 0);
        fill(all(size), 1);
    }

    // Get all root elements
    vi roots()
    {
        vi res;
        int n = parent.size();
        for (int i = 0; i < n; i++)
        {
            if (parent[i] == i)
                res.pb(i);
        }
        return res;
    }

    // Get all connected components
    vvi components()
    {
        int n = parent.size();
        vvi comps(n);
        for (int i = 0; i < n; i++)
        {
            comps[find(i)].pb(i);
        }
        vvi result;
        for (int i = 0; i < n; i++)
        {
            if (!comps[i].empty())
                result.pb(comps[i]);
        }
        return result;
    }
};
struct SegmentTree
{
    int n;
    vi t;
    SegmentTree(const vi& a)
    {
        n = a.size();
        t.resize(4 * n);
        build(a, 1, 0, n - 1);
    }
    void build(const vi& a, int v, int tl, int tr)
    {
        if (tl == tr)
        {
            t[v] = a[tl];
        }
        else
        {
            int tm = (tl + tr) / 2;
            build(a, 2 * v, tl, tm);
            build(a, 2 * v + 1, tm + 1, tr);
            t[v] = t[2 * v] + t[2 * v + 1];
        }
    }
    int query(int l, int r) { return query(1, 0, n - 1, l, r); }
    int query(int v, int tl, int tr, int l, int r)
    {
        if (l > r)
            return 0;
        if (l == tl && r == tr)
            return t[v];
        int tm = (tl + tr) / 2;
        return query(2 * v, tl, tm, l, min(r, tm)) +
            query(2 * v + 1, tm + 1, tr, max(l, tm + 1), r);
    }
    void update(int pos, int val) { update(1, 0, n - 1, pos, val); }
    void update(int v, int tl, int tr, int pos, int val)
    {
        if (tl == tr)
        {
            t[v] = val;
        }
        else
        {
            int tm = (tl + tr) / 2;
            if (pos <= tm)
                update(2 * v, tl, tm, pos, val);
            else
                update(2 * v + 1, tm + 1, tr, pos, val);
            t[v] = t[2 * v] + t[2 * v + 1];
        }
    }
};







//--------- Additional Functions -----------
void solve() {

}

int main() {

    ll S,N;
    cin >> S >>N;

    vi a(N);
    vi b(N);
    vi c(N);
    for (int i = 0; i < N; i++)
    {
        cin >> a[i] >> b[i] >> c[i];
    }
    vi dp(S+1);
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < c[i]; j++)
        {

            for (int x = S; x >= b[i] ; x--)
            {

                dp[x] = max(dp[x],dp[x-b[i]]+a[i]);
            }   
        }
    }

    cout << dp[S] << endl;
    
    


    



    


    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...