解析:第一个第二个都是简单的背包,不解释。
第三个设dp[i][j]为考虑前i个硬币,凑成j的方案数。
状态转移方程:
dp[i][j] = sigma(dp[i-1][j-k*A[i]]) (0<=k<=C[i])
整理后,得
dp[i][j] = dp[i-1][j]+dp[i][j-A[i]]-dp[i-1][j-(C[i]+1)*A[i]]
[1231's code]:
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef long long LL;
const LL MOD = 1e8+7;
const int M = 1e6+6;
int n,m,a[55],c[55];
LL dp[55][1005];
int main(){
int i,j,k,cas,T;
scanf("%d",&cas);
for(T = 1;T <= cas;T++){
scanf("%d%d",&n,&m);
for(i = 1;i <= n;i++) scanf("%d",&a[i]);
for(i = 1;i <= n;i++) scanf("%d",&c[i]);
printf("Case %d: ",T);
memset(dp,0,sizeof(dp));
dp[0][0] = 1;
for(i = 1;i <= n;i++){
for(j = 0;j <= m;j++){
for(k = 0;k <= c[i];k++){
if(j-k*a[i]<0) break;
dp[i][j] = (dp[i][j]+dp[i-1][j-k*a[i]])%MOD;
}
}
}
printf("%lld\n",dp[n][m]);
}
return 0;
}
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef long long LL;
const LL MOD = 1e8+7;
const int M = 1e6+6;
int n,m,a[105];
LL dp[10005];
int main(){
int i,j,k,cas,T;
scanf("%d",&cas);
for(T = 1;T <= cas;T++){
scanf("%d%d",&n,&m);
for(i = 1;i <= n;i++) scanf("%d",&a[i]);
printf("Case %d: ",T);
memset(dp,0,sizeof(dp));
dp[0] = 1;
for(i = 1;i <= n;i++){
for(j = a[i];j <= m;j++){
dp[j] = (dp[j]+dp[j-a[i]])%MOD;
}
}
printf("%lld\n",dp[m]);
}
return 0;
}
[1233's code]:
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef long long LL;
const LL MOD = 1e9+7;
const int M = 1e6+6;
int n,m,a[105],c[105];
LL dp[2][100005];
int main(){
int i,j,k,cas,T;
scanf("%d",&cas);
for(T = 1;T <= cas;T++){
scanf("%d%d",&n,&m);
for(i = 1;i <= n;i++) scanf("%d",&a[i]);
for(i = 1;i <= n;i++) scanf("%d",&c[i]);
printf("Case %d: ",T);
memset(dp,0,sizeof(dp));
dp[0][0] = 1;
int o,p;
for(i = 1;i <= n;i++){
o = i&1;p = (i+1)&1;
for(j = 0;j <= m;j++){
dp[o][j] = dp[p][j]+(j>=a[i]?dp[o][j-a[i]]:0)
-(j>=(c[i]+1)*a[i]?dp[p][j-(c[i]+1)*a[i]]:0);
dp[o][j] = (dp[o][j]%MOD+MOD)%MOD;
}
}
int ans = 0;
for(i = 1;i <= m;i++) if(dp[n&1][i]!=0) ans++;
printf("%d\n",ans);
}
return 0;
}