方法一 ,dp[i][j]表示取前i种硬币满足价值为j的方案数
dp[i][j] =sum(dp[i-1][j-k*a[i]]) k<=j/a[i]
/*
TASK:money
LANG:C++
*/
#include<iostream>
#include<cstdio>
#include<stack>
#include<queue>
#include<algorithm>
#include<cstring>
#include<string>
#include<set>
#include<map>
using namespace std;
typedef long long LL;
const int INF = 1E9 + 10;
const int maxn = 25 + 10;
const int N = 1E4 + 10;
int n,v;
int a[maxn];
LL dp[maxn][N];
void solve()
{
scanf("%d%d",&n,&v);
for(int i = 0;i<n;i++)
{
scanf("%d",&a[i]);
}
//处理边界,当总共要拿j元时,如果j是第一种硬币的整数倍,那么ways[0][j] = 1;
for(int i = 1;i<=v;i++)
{
if(i%a[0]==0)
{
dp[0][i] = 1;
}
else
{
dp[0][i] = 0 ;
}
}
//cout<<1<<endl;
//处理边界,当总共要拿0元的时候,方案数为1
for(int i = 0;i<n;i++)
{
dp[i][0] =1;
}
//cout<<1<<endl;
for(int i =1;i<n;i++)
{
for(int j =1;j<=v;j++)
{
//第i种硬币拿取的个数
//当从第i种硬币中得到的钱不超过j时
for(int k = 0;k*a[i]<=j;k++)
{
dp[i][j] +=dp[i-1][j-k*a[i]];
}
}
}
LL ans = dp[n-1][v];
printf("%lld\n",ans);
}
int main()
{
freopen("money.in","r",stdin);
freopen("money.out","w",stdout);
solve();
return 0;
}
方法二
dp[i][j] = dp[i-1][j] + dp[i-1][j-a[i]]
dp[i][j] = dp[i-1][j]
/*
TASK:money
LANG:C++
*/
#include<iostream>
#include<cstdio>
#include<stack>
#include<queue>
#include<algorithm>
#include<cstring>
#include<string>
#include<set>
#include<map>
using namespace std;
typedef long long LL;
const int INF = 1E9 + 10;
const int maxn = 25 + 10;
const int N = 1E4 + 10;
int n,v;
int a[maxn];
LL dp[maxn][N];
void solve()
{
scanf("%d%d",&n,&v);
for(int i = 0;i<n;i++)
{
scanf("%d",&a[i]);
}
//处理边界,当总共要拿j元时,如果j是第一种硬币的整数倍,那么ways[0][j] = 1;
for(int i = 1;i<=v;i++)
{
if(i%a[0]==0)
{
dp[0][i] = 1;
}
else
{
dp[0][i] = 0 ;
}
}
//cout<<1<<endl;
//处理边界,当总共要拿0元的时候,方案数为1
for(int i = 0;i<n;i++)
{
dp[i][0] =1;
}
//cout<<1<<endl;
/*for(int i =1;i<n;i++)
{
for(int j =1;j<=v;j++)
{
//第i种硬币拿取的个数
//当从第i种硬币中得到的钱不超过j时
for(int k = 0;k*a[i]<=j;k++)
{
dp[i][j] +=dp[i-1][j-k*a[i]];
}
}
}*/
for(int i =1;i<n;i++)
{
for(int j =1;j<=v;j++)
{
if(j-a[i]>=0)
{
dp[i][j] = dp[i-1][j] + dp[i][j-a[i]];
}
else
{
dp[i][j] = dp[i-1][j];
}
}
}
LL ans = dp[n-1][v];
printf("%lld\n",ans);
}
int main()
{
freopen("money.in","r",stdin);
freopen("money.out","w",stdout);
solve();
return 0;
}
/*
TASK:money
LANG:C++
*/
#include<iostream>
#include<cstdio>
#include<stack>
#include<queue>
#include<algorithm>
#include<cstring>
#include<string>
#include<set>
#include<map>
using namespace std;
typedef long long LL;
const int INF = 1E9 + 10;
const int maxn = 25 + 10;
const int N = 1E4 + 10;
int n,v;
int a[maxn];
LL dp[maxn][N];
LL d[N];
void solve()
{
scanf("%d%d",&n,&v);
for(int i = 0;i<n;i++)
{
scanf("%d",&a[i]);
}
//处理边界,当总共要拿j元时,如果j是第一种硬币的整数倍,那么ways[0][j] = 1;
for(int i = 0;i<=v;i++)
{
if(i%a[0]==0)
{
d[i] = 1;
}
else
{
d[i] = 0 ;
}
}
//cout<<1<<endl;
//处理边界,当总共要拿0元的时候,方案数为1
/*for(int i = 0;i<n;i++)
{
dp[i][0] =1;
}*/
//cout<<1<<endl;
/*for(int i =1;i<n;i++)
{
for(int j =1;j<=v;j++)
{
//第i种硬币拿取的个数
//当从第i种硬币中得到的钱不超过j时
for(int k = 0;k*a[i]<=j;k++)
{
dp[i][j] +=dp[i-1][j-k*a[i]];
}
}
}*/
/* for(int i =1;i<n;i++)
{
for(int j =1;j<=v;j++)
{
if(j-a[i]>=0)
{
dp[i][j] = dp[i-1][j] + dp[i][j-a[i]];
}
else
{
dp[i][j] = dp[i-1][j];
}
}
}
LL ans = dp[n-1][v];*/
for(int i =1;i<n;i++)
{
for(int j =1;j<=v;j++)
{
if(j-a[i]>=0)
{
d[j] = d[j] + d[j-a[i]];
}
else
{
d[j] = d[j];
}
}
}
printf("%lld\n",d[v]);
}
int main()
{
freopen("money.in","r",stdin);
freopen("money.out","w",stdout);
solve();
return 0;
}