平衡方案
Description
天平的一側物體重量爲M,該天平有N種砝碼,每種砝碼都有很多,求保持天平平衡,砝碼搭配的方案數。
Input
第二行兩個整數N,M
第二行N個整數,表示各種砝碼的重量
Output
一個整數 ANS 表示所有非負整數對(X1,X2,。。。Xn)的個數,如果答案超過了9位數,你只需輸出ANS mod 10^9的值即可。
Sample Input Copy
5 5
1 2 3 4 5
Sample Output Copy
7
HINT
數據規模
1<=N<=1000,0<=M<=1000
分析
不同於之前的平衡方案,這裏是有一個關鍵詞的——“有n種砝碼”,也就是說,數量是無限的
當然,是在可取的範圍內無限的(不超出要稱重的物品的質量
同樣,我們從 f[n][m] 放到第n種砝碼時的方案數來分析
但是一個砝碼能用多次
所以這裏,我們可以將一個物品的取的數量限定爲 k
k 的範圍便是 0 ≤ k ≤ m/a[n] (a[n]表示第n個砝碼的質量)
因爲 k 的取值可以是零,也就是不放,所以我們這裏可以取消對不放的特判
而是主要來判斷放的情況
同樣,如果放一個或是多個的話,都是用 k 來代表的
所以我們可以得到狀態轉移方程:
f[n][m] += f[n-1][m-a[i]*k] (a[n]表示第n個砝碼的質量)
同樣,後面便是到初始化了
相同於前面的,這裏也給出圖來:
圖中黃色的部分也就是我們初始化爲1的地方
在稱質量爲0的物品時,我們只有一種方法,什麼都不放
之後是第一行
在不超過需要稱重的物品的質量的範圍內我們可以用 k * a[1] 稱出的質量同樣初始化爲1
代碼
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <math.h>
#include <stdio.h>
#include <queue>
#include <stack>
#include <vector>
using namespace std;
long long mod = 1000000000;
int f[1009][1009],a[1009];
int n,m;
int main() {
scanf("%d %d",&n,&m);
for (int i = 1; i <= n; i++) scanf("%d",&a[i]);
for (int i = 1; i <= n; i++) f[i][0] = 1;
for (int j = 1; j <= m; j++) if (j % a[1] == 0) f[1][j] = 1;
//for (int j = 1; j <= m; j++) f[1][j] = j/a[1]; 也可以這樣寫
for (int i = 2; i <= n; i++)
for (int j = 1; j <= m; j++)
for (int k = 0; k <= j/a[i]; k++)
f[i][j] += f[i-1][j-a[i]*k],
f[i][j] %= mod;
printf("%d",f[n][m]);
return 0;
}