Luogu P1450 Problem Solving Report

P1450. Coin Shopping

Topic description

There are a total of \(4\) coins for coin shopping . The face values ​​are \(c1,c2,c3,c4\) respectively . Someone goes to the store to buy something, and goes \(tot\) times. Every time you bring \(d_i\) pieces of \(c_i\) coins, buy something worth \(s_i\) . How many payment methods are available each time.

Input and output format

Input format:

The first line \(c_1,c_2,c_3,c_4,tot\) below \(tot\) line \(d_1,d_2,d_3,d_4,s\)

Output format:

methods per time

illustrate

\ (in, s <= 100000 \)

\ (all <= 1000 \)


It's easy to think of, converts into multiple backpacks

        dp[0]=1;
        for(int i=1;i<=4;i++)
            for(int k=s;k>=0;k--)
                if(dp[k])
                    for(int j=1;j<=a[i];j++)
                        dp[k+j*c[i]]+=dp[k];
        printf("%d\n",dp[s]);

The result is of course \(t\) flying


If we do it as a full backpack, part of it is illegal when the number of items in it is greater than the limit.

Assuming that only for items with a value of \(c\) \(i\) , there is an upper limit of quantity \(d\) , and the amount of money to be made up is \(s\) .

\(dp[s]\) is the number of solutions to make up \(s\ ) when installing unlimited \(i\)

\(dp[sc*(d+1)]\) is the number of solutions to make up \(sc*(d+1)\ ) when infinite \(i\ ) is installed

What do you get by subtracting? Not only the number of solutions when the loading limit is \(d\)


However, this is only for one item, what if there are multiple items?

If there are multiple constraints intersecting, then according to the principle of inclusion and exclusion, more can be reduced and less can be added back.

code

#include <cstdio>
#define ll long long
const int N=100010;
int c[5],tot,a[5],s;
ll dp[N];
int main()
{
    for(int i=1;i<=4;i++) scanf("%d",c+i);
    scanf("%d",&tot);
    dp[0]=1;
    for(int i=1;i<=4;i++)
        for(int j=c[i];j<=N;j++)
            dp[j]+=dp[j-c[i]];
    while(tot--)
    {
        for(int i=1;i<=4;i++) scanf("%d",a+i);
        scanf("%d",&s);
        ll ans=0;
        for(int i=0;i<=15;i++)
        {
            int flag=0,t=0;
            for(int j=1;j<=4;j++)
                if((i>>j-1)&1)
                {
                    t+=c[j]*(a[j]+1);
                    flag^=1;
                }
            ll tt=(s>=t?dp[s-t]:0);
            ans+=(flag?-tt:tt);
        }
        printf("%lld\n",ans);
    }
    return 0;
}

Note the method of enumerating subsets at this time.


2018.5.4

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325367631&siteId=291194637