把(0,0)也视为一个 ki 。
显然要容斥原理。
枚举一个s,去求至少有s步是不合法的方案数。
这个要dp三个东西。
fi,j 表示走了i步, ∑k =j*10的方案数。
横纵坐标没有关联,可以分开dp。
pi,j 表示走了i步,横坐标之和为j的方案数。
qi,j 表示走了i步,纵坐标之和为j的方案数。
那么 Ans=∑i,j(−1)i∗(ri)∗fi,j∗pr−i,tx−j∗10∗qr−i,ty−j∗10
这个为什么是对的呢。
考虑一种确切的走法,它有t步是不合法的。
在上面那个式子中,它会被计算 ∑ti=0(−1)i∗(ti)=[t=0]
所以上面那个式子刚好只会计算没有出现过不合法的方案数。
这个好像是先有结论再有证明,但是似乎也只能是这样了。
#include
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
#define fo(i, x, y) for(int i = x; i <= y; i ++)
using namespace std;
const int mo = 1e4 + 7;
int tx, ty, mx, my, r, K, k[55], ans, bz[81];
int f[1605][81], p[1605][801], q[1605][801], s[801], c[1601][1601];
int main() {
freopen("jump.in", "r", stdin);
freopen("jump.out", "w", stdout);
scanf("%d %d %d %d %d %d", &tx, &ty, &mx, &my, &r, &K);
fo(i, 1, K) scanf("%d", &k[i]), bz[k[i] / 10] = 1;
mx = min(mx, tx); my = min(my, ty); bz[0] = 1;
f[0][0] = 1;
fo(i, 1, r) fo(j, 0, min(tx, ty) / 10) fo(u, 0, j)
if(bz[j - u]) f[i][j] = (f[i - 1][u] + f[i][j]) % mo;
fo(j, 0, tx) s[j] = 1;
fo(i, 1, r) {
fo(j, 0, tx) p[i][j] = (s[j] - ((j - mx - 1 < 0) ? 0 : s[j - mx - 1]) + mo) % mo;
s[0] = p[i][0];
fo(j, 1, tx) s[j] = (p[i][j] + s[j - 1]) % mo;
}
fo(j, 0, ty) s[j] = 1;
fo(i, 1, r) {
fo(j, 0, ty) q[i][j] = (s[j] - ((j - my - 1 < 0) ? 0 : s[j - my - 1]) + mo) % mo;
s[0] = q[i][0];
fo(j, 1, ty) s[j] = (q[i][j] + s[j - 1]) % mo;
}
c[0][0] = 1;
fo(i, 1, r) {
c[i][0] = 1;
fo(j, 1, i) c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % mo;
}
fo(i, 0, r) fo(j, 0, min(tx, ty) / 10)
ans += ((i % 2) ? -1 : 1) * f[i][j] % mo * p[r - i][tx - j * 10] % mo * q[r - i][ty - j * 10] % mo * c[r][i] % mo;
printf("%d", (ans % mo + mo) % mo);
}