1 条题解

  • 1
    @ 2023-4-28 10:17:09

    手动容斥

    #include <bits/stdc++.h>
    #define int long long
    using namespace std;
    const int MAXS = 100000;
    int c[5], n, d[5], cd[5], s;
    int f[MAXS + 5]; // f[i]: 不考虑硬币数量限制时,i块钱有几种方案
    int cal()
    {
        for (int i = 1; i <= 4; i++)
            cd[i] = c[i] * (d[i] + 1);
        int ans = f[s];
        if (s >= cd[1])
            ans -= f[s - cd[1]];
        if (s >= cd[2])
            ans -= f[s - cd[2]];
        if (s >= cd[3])
            ans -= f[s - cd[3]];
        if (s >= cd[4])
            ans -= f[s - cd[4]];
        if (s >= cd[1] + cd[2])
            ans += f[s - cd[1] - cd[2]];
        if (s >= cd[1] + cd[3])
            ans += f[s - cd[1] - cd[3]];
        if (s >= cd[1] + cd[4])
            ans += f[s - cd[1] - cd[4]];
        if (s >= cd[2] + cd[3])
            ans += f[s - cd[2] - cd[3]];
        if (s >= cd[2] + cd[4])
            ans += f[s - cd[2] - cd[4]];
        if (s >= cd[3] + cd[4])
            ans += f[s - cd[3] - cd[4]];
        if (s >= cd[1] + cd[2] + cd[3])
            ans -= f[s - cd[1] - cd[2] - cd[3]];
        if (s >= cd[1] + cd[2] + cd[4])
            ans -= f[s - cd[1] - cd[2] - cd[4]];
        if (s >= cd[1] + cd[3] + cd[4])
            ans -= f[s - cd[1] - cd[3] - cd[4]];
        if (s >= cd[2] + cd[3] + cd[4])
            ans -= f[s - cd[2] - cd[3] - cd[4]];
        if (s >= cd[1] + cd[2] + cd[3] + cd[4])
            ans += f[s - cd[1] - cd[2] - cd[3] - cd[4]];
        return ans;
    }
    signed main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        cin >> c[1] >> c[2] >> c[3] >> c[4] >> n;
        f[0] = 1;
        for (int i = 1; i <= 4; i++)
            for (int j = c[i]; j <= MAXS; j++)
                f[j] += f[j - c[i]];
        while (n--)
        {
            cin >> d[1] >> d[2] >> d[3] >> d[4] >> s;
            cout << cal() << "\n";
        }
    
        return 0;
    }
    

    位运算枚举子集计算容斥

    #include <bits/stdc++.h>
    #define int long long
    using namespace std;
    const int MAXS = 100000;
    int c[5], n, d[5], cd[5], s;
    int f[MAXS + 5]; // f[i]: 不考虑硬币数量限制时,i块钱有几种方案
    int cal()
    {
        for (int i = 1; i <= 4; i++)
            cd[i] = c[i] * (d[i] + 1);
        int ans = 0;
        for (int sta = 0; sta <= (1 << 4) - 1; sta++)
        {
            int flag = 1;
            int nowSum = 0;
            for (int i = 1; i <= 4; i++)
                if (sta & (1 << (i - 1)))
                {
                    // 当前状态右数第 i 位是 1
                    flag = -flag;
                    nowSum += cd[i];
                }
            if (s >= nowSum)
                ans += flag * f[s - nowSum];
        }
        return ans;
    }
    signed main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        cin >> c[1] >> c[2] >> c[3] >> c[4] >> n;
        f[0] = 1;
        for (int i = 1; i <= 4; i++)
            for (int j = c[i]; j <= MAXS; j++)
                f[j] += f[j - c[i]];
        while (n--)
        {
            cin >> d[1] >> d[2] >> d[3] >> d[4] >> s;
            cout << cal() << "\n";
        }
        return 0;
    }
    
    • 1

    信息

    ID
    1274
    时间
    1000ms
    内存
    162MiB
    难度
    6
    标签
    递交数
    26
    已通过
    11
    上传者