最后一条限制不好处理, 于是关于 小 的 背包信息 搜出来, 售货员 的背包信息 ,
但是忘记 记忆化 了, 丢了 …
AC 代码
#include<bits/stdc++.h>
#define reg register
int read(){
char c;
int s = 0, flag = 1;
while((c=getchar()) && !isdigit(c))
if(c == '-'){ flag = -1, c = getchar(); break ; }
while(isdigit(c)) s = s*10 + c-'0', c = getchar();
return s * flag;
}
const int maxn = 1000006;
const int mod = 1e9 + 7;
int N;
int X;
int Ans;
int F2[maxn];
int F3[maxn];
int F4[1005][20005];
struct Node{ int a, b, c; } A[maxn];
int DFS(int k, int s){
if(k == N+1){ if(s < X) return 0; return F2[s - X]; }
if(~F4[k][s]) return F4[k][s];
int res = 0;
for(reg int i = 1; i <= A[k].b; i ++){
int ns = s + A[k].a*i;
if(ns - X >= A[k].a) break ;
res += DFS(k+1, ns); res %= mod;
}
res += DFS(k+1, s); res %= mod;
return F4[k][s] = res;
}
int main(){
N = read(), X = read();
for(reg int i = 1; i <= N; i ++) A[i].a = read(), A[i].b = read(), A[i].c = read();
std::reverse(A+1, A+N+1); F2[0] = 1;
for(reg int i = 1; i <= N; i ++){
for(reg int j = 0; j <= X; j ++) F3[j] = F2[j];
for(reg int k = 1; k <= A[i].c; k <<= 1){
for(reg int j = X; j >= k*A[i].a; j --) F2[j] = (F2[j] + F3[j-k*A[i].a]) % mod;
A[i].c -= k;
}
if(A[i].c > 0)
for(reg int j = X; j >= A[i].c*A[i].a; j --) F2[j] = (F2[j] + F3[j-A[i].c*A[i].a]) % mod;
}
memset(F4, -1, sizeof F4);
printf("%d
", DFS(1, 0));
return 0;
}
设 表示 小 凑出 的方案数, 表示 售货员 凑出 的方案数,
但是题目中对 小 的钱数 有限制, 于是先使用 完全背包 更新一遍 ,
然后 减去 得到 满足 物品个数限制 .
状态转移时 限制上界 为 加 倒序循环 满足 纸币面值限制 .
#include<bits/stdc++.h>
#define reg register
int read(){
char c;
int s = 0, flag = 1;
while((c=getchar()) && !isdigit(c))
if(c == '-'){ flag = -1, c = getchar(); break ; }
while(isdigit(c)) s = s*10 + c-'0', c = getchar();
return s * flag;
}
const int maxn = 1000006;
const int mod = 1e9 + 7;
int N;
int X;
int Ans;
int a[maxn];
int b[maxn];
int c[maxn];
int F1[maxn];
int F2[maxn];
int main(){
N = read(), X = read();
for(reg int i = 1; i <= N; i ++) a[i] = read(), b[i] = read(), c[i] = read();
F1[0] = F2[0] = 1;
for(reg int i = N; i >= 1; i --){
for(reg int j = a[i]; j < X+a[i]; j ++) F1[j] = (F1[j] + F1[j-a[i]]) % mod;
for(reg int j = X+a[i]-1; j >= a[i]*(b[i]+1); j --) F1[j] = (F1[j] - F1[j-a[i]*(b[i]+1)] + mod) % mod;
for(reg int j = a[i]; j < X<<1; j ++) F2[j] = (F2[j] + F2[j-a[i]]) % mod;
for(reg int j = 2*X-1; j >= a[i]*(c[i]+1); j --) F2[j] = (F2[j] - F2[j-a[i]*(c[i]+1)] + mod) % mod;
}
for(reg int y = X; y <= 2*X-1; y ++) Ans = (Ans + 1ll*F1[y]*F2[y-X]%mod) % mod;
printf("%d
", Ans);
return 0;
}