题目链接:
https://www.luogu.com.cn/problem/CF543A
#完全背包
和 [[LG P1586 四方定理]] 一模一样
完全背包求方案数
n 个物品,每个物品一维体积为 1,二维体积为 a_i
题目中要求一维体积恰好装满,二维体积不超过的方案数,所以就把状态定义为一二维都恰好装满就行
从集合角度来考虑:
- 集合定义
- f [ i ] [ j ] [ k ] f[i][j][k] f[i][j][k]:
- Sum
- 集合划分:
+
注意为什么要从 f[0][m]
开始统计:因为 f[0][m]
最后代表的是前 n 个物品,m 行代码,bug数为 0 的情况,这种情况是合法的
代码
import java.io.*;
import java.math.BigInteger;
import java.util.*;
import static java.lang.Math.*;
public class Main{
static int status;
static BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));
static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
static PrintWriter cout = new PrintWriter(bw);
static StreamTokenizer st = new StreamTokenizer(buf);
public static int nextInt() throws IOException {
status = st.nextToken();
return (int) st.nval;
}
static int n, m, b, mod;
static int[] a;
static long[][] f;
static final int INF = 0x3f3f3f3f, MOD = (int) 1e9 + 7;
public static void main(String[] args) throws IOException {
n = nextInt();
m = nextInt();
b = nextInt();
mod = nextInt();
a = new int[n+1];
f = new long[b+1][m+1];
for(int i=1;i<=n;i++)
a[i] = nextInt();
f[0][0]=1;
for(int i=1;i<=n;i++)
for(int j=a[i];j<=b;j++)
for(int k=1;k<=m;k++)
f[j][k]=(f[j][k]+f[j-a[i]][k-1])%mod;
long ans=0;
for(int i=0;i<=b;i++)
ans=(ans+f[i][m])%mod;
cout.println(ans);
cout.flush();
}// End of main
}