Address
Solution
题目给出 3 3 3 个限制:
- x ≤ x ′ ≤ x + M x , y ≤ y ′ ≤ y + M y x\leq x'\leq x+M_x , y\leq y'\leq y+M_y x≤x′≤x+Mx,y≤y′≤y+My
- 每一步都不能停在原地
- 每一步 x , y x,y x,y 的增量不能同时等于 k i k_i ki
先考虑怎么满足限制 1 1 1:
发现两维之间独立,可以分别计算答案然后相乘。那么问题转化为在数轴上从 0 0 0 走到 T x T_x Tx,走 R R R 步,每一步满足 x ≤ x ′ ≤ x + M x x\leq x'\leq x+M_x x≤x′≤x+Mx。
记 f ( i ) f(i) f(i) 表示恰好有 i i i 步超过步长限制的方案数。 g ( i ) g(i) g(i) 表示至少有 i i i 步超过步长限制的方案数,那么有 g ( i ) = C R i × C T x − i ( M x + 1 ) + R − 1 R − 1 g(i)=C_R^i×C_{T_x-i(M_x+1)+R-1}^{R-1} g(i)=CRi×CTx−i(Mx+1)+R−1R−1。显然每个 f ( j ) f(j) f(j) 都在 g ( i ) g(i) g(i) 中被算了 C j i C_j^i Cji 次,即 g ( i ) = ∑ j = i R C j i × f ( j ) g(i)=\sum_{j=i}^RC_j^i×f(j) g(i)=∑j=iRCji×f(j)。
下面证明 g ( i ) = ∑ j = i R f ( j ) g(i)=\sum_{j=i}^Rf(j) g(i)=∑j=iRf(j) 等价于 f ( i ) = ∑ j = i R ( − 1 ) j − i × C j i × g ( j ) f(i)=\sum_{j=i}^R(-1)^{j-i}×C_j^i×g(j) f(i)=∑j=iR(−1)j−i×Cji×g(j):
∑ j = i R ( − 1 ) j − i × C j i × g ( j ) = ∑ j = i R ( − 1 ) j − i × C j i × ∑ k = j R × C k j × f ( k ) \sum_{j=i}^R(-1)^{j-i}×C_j^i×g(j)=\sum_{j=i}^R(-1)^{j-i}×C_j^i×\sum_{k=j}^R×C_k^j×f(k) j=i∑R(−1)j−i×Cji×g(j)=j=i∑R(−1)j−i×Cji×k=j∑R×Ckj×f(k) = ∑ k = i R ( ∑ j = i k ( − 1 ) j − i × C j i × C k j ) × f ( k ) =\sum_{k=i}^R(\sum_{j=i}^k(-1)^{j-i}×C_j^i×C_k^j)×f(k) =k=i∑R(j=i∑k(−1)j−i×Cji×Ckj)×f(k)
把
∑
j
=
i
k
(
−
1
)
j
−
i
×
C
j
i
×
C
k
j
\sum_{j=i}^k(-1)^{j-i}×C_j^i×C_k^j
∑j=ik(−1)j−i×Cji×Ckj 单独拿出来考虑:
∑
j
=
i
k
(
−
1
)
j
−
i
×
C
j
i
×
C
k
j
=
C
k
i
∑
j
=
i
k
(
−
1
)
j
−
i
×
C
k
−
i
j
−
i
=
C
k
i
∑
j
=
0
k
−
i
(
−
1
)
j
×
C
k
−
i
j
\sum_{j=i}^k(-1)^{j-i}×C_j^i×C_k^j=C_k^i\sum_{j=i}^k(-1)^{j-i}×C_{k-i}^{j-i}=C_k^i\sum_{j=0}^{k-i}(-1)^j×C_{k-i}^j
j=i∑k(−1)j−i×Cji×Ckj=Ckij=i∑k(−1)j−i×Ck−ij−i=Ckij=0∑k−i(−1)j×Ck−ij 发现只有在
k
=
i
k=i
k=i 的时候上式为
1
1
1,
k
≠
i
k≠i
k=i 时上式都为
0
0
0,那么:
∑
k
=
i
R
(
∑
j
=
i
k
(
−
1
)
j
−
i
×
C
j
i
×
C
k
j
)
×
f
(
k
)
=
f
(
i
)
\sum_{k=i}^R(\sum_{j=i}^k(-1)^{j-i}×C_j^i×C_k^j)×f(k)=f(i)
k=i∑R(j=i∑k(−1)j−i×Cji×Ckj)×f(k)=f(i)
证毕。
我们要求的就是 f ( 0 ) = ∑ i = 0 R ( − 1 ) i − 0 × C i 0 × g ( i ) = ∑ i = 0 R ( − 1 ) i × g ( i ) f(0)=\sum_{i=0}^R(-1)^{i-0}×C_i^0×g(i)=\sum_{i=0}^R(-1)^i×g(i) f(0)=i=0∑R(−1)i−0×Ci0×g(i)=i=0∑R(−1)i×g(i)
接下来考虑限制 2 2 2。
记
h
(
i
)
h(i)
h(i) 表示走
i
i
i 步到终点,每步都满足限制
1
,
2
1,2
1,2 的方案数,
p
(
i
)
p(i)
p(i) 表示走
i
i
i 步到终点,每步都满足限制
1
1
1 的方案数,可以直接由
f
f
f 得出。枚举强制
j
j
j 步必须满足限制
2
2
2,剩下
i
−
j
i-j
i−j 步停在原地,那么有:
p
(
i
)
=
∑
j
=
0
i
C
i
j
×
h
(
j
)
p(i)=\sum_{j=0}^iC_i^j×h(j)
p(i)=j=0∑iCij×h(j)
反演可得(证明类似
f
,
g
f,g
f,g 的关系式):
h
(
R
)
=
∑
j
=
0
i
(
−
1
)
R
−
i
×
C
R
i
×
p
(
i
)
h(R)=\sum_{j=0}^i(-1)^{R-i}×C_R^i×p(i)
h(R)=j=0∑i(−1)R−i×CRi×p(i)
接下来考虑限制 3 3 3。
记 a ( i ) a(i) a(i) 表示走 R R R 步到终点,每步都满足限制 1 , 2 1,2 1,2,至少有 i i i 步走了非法向量的方案数,记 c a l c ( T x , T y , M x , M y , R ) calc(T_x,T_y,M_x,M_y,R) calc(Tx,Ty,Mx,My,R) 表示题目去掉第 3 3 3 个限制之后,走 R R R 步到 T x , T y T_x,T_y Tx,Ty,每一步满足 x ≤ x ′ ≤ x + M x , y ≤ y ′ ≤ y + M y x\leq x'\leq x+M_x , y\leq y'\leq y+M_y x≤x′≤x+Mx,y≤y′≤y+My 的方案数。
先用背包预处理出 S ( i , j ) S(i,j) S(i,j) 表示选出 i i i 个非法向量, ∑ k i = j G \sum k_i=jG ∑ki=jG 的方案数,然后有: a ( i ) = ∑ j S ( i , j ) × c a l c ( T x − j G , T y − j G , M x , M y , R − j ) × C R i a(i)=\sum_jS(i,j)×calc(T_x-jG,T_y-jG,M_x,M_y,R-j)×C_R^i a(i)=j∑S(i,j)×calc(Tx−jG,Ty−jG,Mx,My,R−j)×CRi
记 b ( i ) b(i) b(i) 表示走 R R R 步到终点,每步都满足限制 1 , 2 1,2 1,2,恰好有 i i i 步走了非法向量的方案数,显然有 a ( i ) = ∑ j = i R C j i × b ( j ) a(i)=\sum_{j=i}^RC_j^i×b(j) a(i)=j=i∑RCji×b(j) 同样反演可得 b ( 0 ) = ∑ i = 0 R ( − 1 ) i a ( i ) b(0)=\sum_{i=0}^R(-1)^ia(i) b(0)=i=0∑R(−1)ia(i)
时间复杂度 O ( \mathcal O( O(跑的飞快 ) ) )。
Code
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1e6, e = 1005, o = 105, mod = 1e9 + 7;
int Tx, Ty, Mx, My, R, G, n, a[e], ans, S[e][e], Lim, g[e];
int fac[N + 5], inv[N + 5];
inline int ksm(int x, int y)
{
int res = 1;
while (y)
{
if (y & 1) res = (ll)res * x % mod;
y >>= 1;
x = (ll)x * x % mod;
}
return res;
}
inline void add(int &x, int y)
{
(x += y) >= mod && (x -= mod);
}
inline int plu(int x, int y)
{
add(x, y);
return x;
}
inline int c(int x, int y)
{
if (x < y) return 0;
if (x == y) return 1;
return (ll)fac[x] * inv[x - y] % mod * inv[y] % mod;
}
inline int solve(int Tx, int Mx, int R)
{
int res = 0;
for (int i = 0; i <= R; i++)
if ((Mx + 1) * i <= Tx)
{
int v = (ll)c(R, i) * c(Tx - i * (Mx + 1) + R - 1, R - 1) % mod;
if (i & 1) add(res, mod - v);
else add(res, v);
}
else break;
return res;
}
inline int calc(int Tx, int Ty, int Mx, int My, int R)
{
if (Tx < 0 || Ty < 0) return 0;
int res = 0;
for (int i = 0; i <= R; i++)
{
int v = (ll)solve(Tx, Mx, i) * solve(Ty, My, i) % mod * c(R, i) % mod;
if ((R - i) & 1) v = mod - v;
add(res, v);
}
return res;
}
int main()
{
cin >> Tx >> Ty >> Mx >> My >> R >> G >> n;
int i, j, k, h;
Lim = min(Tx, Ty); Lim /= G;
for (i = 1; i <= n; i++)
cin >> a[i], a[i] /= G;
sort(a + 1, a + n + 1);
n = unique(a + 1, a + n + 1) - a - 1;
fac[0] = 1;
for (i = 1; i <= N; i++)
fac[i] = (ll)fac[i - 1] * i % mod;
inv[N] = ksm(fac[N], mod - 2);
for (i = N - 1; i >= 0; i--)
inv[i] = (ll)inv[i + 1] * (i + 1) % mod;
S[0][0] = 1;
for (i = 1; i <= R; i++)
for (j = 1; j <= n; j++)
for (k = 0; k <= Lim - a[j]; k++)
add(S[i][k + a[j]], S[i - 1][k]);
for (i = 0; i <= min(R, Lim); i++)
for (j = 0; j <= Lim; j++)
if (S[i][j]) g[i] = (g[i] + (ll)S[i][j] *
calc(Tx - j * G, Ty - j * G, Mx, My, R - i) % mod * c(R, i)) % mod;
for (i = 0; i <= min(R, Lim); i++)
if (i & 1) add(ans, mod - g[i]);
else add(ans, g[i]);
cout << ans << endl;
return 0;
}