51nod 1838
http://www.51nod.com/Challenge/Problem.html#!#problemId=1838
题目中有一个很巧妙的反演。由于之前没接触过这类题目。第一次接触,感觉学到了很多东西。
首先。计算,无限限制的情况下,从 ( 0 , 0 ) (0,0) (0,0)走到 ( x , y ) (x,y) (x,y),不走 ( 0 , 0 ) (0,0) (0,0)向量的方案数。
由于
x
x
x方向和
y
y
y方向有一定关系,又相互独立。
令
A
(
M
,
R
,
t
)
A(M,R,t)
A(M,R,t)表示:
∑
i
R
a
i
=
t
,
a
i
∈
[
0
,
M
]
\sum_i^Ra_i = t,a_i\in[0,M]
i∑Rai=t,ai∈[0,M]
的答案个数。
则有:
∑
i
>
=
0
A
(
M
,
R
,
t
)
x
t
=
(
∑
i
=
0
M
x
i
)
R
\sum_{i>=0}A(M,R,t)x^t=\Big(\sum_{i=0}^Mx^i\Big)^R
i>=0∑A(M,R,t)xt=(i=0∑Mxi)R
(
∑
i
=
0
M
x
i
)
R
=
(
1
−
x
M
+
1
1
−
x
)
R
=
(
1
−
x
)
−
R
∑
a
=
0
R
(
R
a
)
(
−
1
)
a
x
(
M
+
1
)
a
\Big(\sum_{i=0}^Mx^i\Big)^R =\Big(\frac{1-x^{M+1}}{1-x}\Big)^R=(1-x)^{-R}\sum_{a=0}^R\binom{R}{a}(-1)^ax^{(M+1)a}
(i=0∑Mxi)R=(1−x1−xM+1)R=(1−x)−Ra=0∑R(aR)(−1)ax(M+1)a
=
∑
a
=
0
R
(
R
a
)
(
−
1
)
a
x
(
M
+
1
)
a
∑
b
>
=
0
(
R
+
b
−
1
b
)
x
b
=\sum_{a=0}^R\binom{R}{a}(-1)^ax^{(M+1)a}\sum_{b>=0}\binom{R+b-1}{b}x^b
=a=0∑R(aR)(−1)ax(M+1)ab>=0∑(bR+b−1)xb
则有:
A
(
M
,
R
,
x
)
=
∑
a
=
0
R
(
R
a
)
(
−
1
)
a
(
R
+
(
x
−
(
M
+
1
)
a
)
−
1
x
−
(
M
+
1
)
a
)
A(M,R,x) =\sum_{a=0}^R\binom{R}{a}(-1)^a\binom{R+(x-(M+1)a)-1}{x-(M+1)a}
A(M,R,x)=a=0∑R(aR)(−1)a(x−(M+1)aR+(x−(M+1)a)−1)
令
D
d
(
R
,
x
,
y
)
D_d(R,x,y)
Dd(R,x,y)为
(
0
,
0
)
(0,0)
(0,0)到
(
x
,
y
)
(x,y)
(x,y)走
R
R
R步,
d
d
d个
(
0
,
0
)
(0,0)
(0,0)向量的方案数.
那么有:
∑
t
=
0
R
∑
d
=
0
t
(
t
d
)
D
t
(
R
,
x
,
y
)
=
∑
d
=
0
R
(
R
d
)
A
(
M
x
,
R
−
d
,
x
)
A
(
M
y
,
R
−
d
,
y
)
\sum_{t=0}^R\sum_{d=0}^t\binom{t}{d}D_t(R,x,y)=\sum_{d=0}^R\binom{R}{d}A(M_x,R-d,x)A(M_y,R-d,y)
t=0∑Rd=0∑t(dt)Dt(R,x,y)=d=0∑R(dR)A(Mx,R−d,x)A(My,R−d,y)
上面这个式子成立,是因为左边插板法对应右边
D
t
D_t
Dt的
d
d
d选择.
那么有:
∑
t
=
0
R
∑
d
=
0
t
(
t
d
)
D
t
(
R
,
x
,
y
)
(
−
1
)
d
\sum_{t=0}^R\sum_{d=0}^t\binom{t}{d}D_t(R,x,y)(-1)^d
t=0∑Rd=0∑t(dt)Dt(R,x,y)(−1)d
=
∑
d
=
0
R
(
R
d
)
A
(
M
x
,
R
−
d
,
x
)
A
(
M
y
,
R
−
d
,
y
)
(
−
1
)
d
=\sum_{d=0}^R\binom{R}{d}A(M_x,R-d,x)A(M_y,R-d,y)(-1)^d
=d=0∑R(dR)A(Mx,R−d,x)A(My,R−d,y)(−1)d
其中:
∑
t
=
0
R
∑
d
=
0
t
(
t
d
)
D
t
(
R
,
x
,
y
)
(
−
1
)
d
\sum_{t=0}^R\sum_{d=0}^t\binom{t}{d}D_t(R,x,y)(-1)^d
t=0∑Rd=0∑t(dt)Dt(R,x,y)(−1)d
=
∑
t
=
0
R
D
t
(
R
,
x
,
y
)
(
1
−
1
)
t
=
D
0
(
R
,
x
,
y
)
=\sum_{t=0}^RD_t(R,x,y)(1-1)^t=D_0(R,x,y)
=t=0∑RDt(R,x,y)(1−1)t=D0(R,x,y)
令
d
p
[
x
]
[
t
]
dp[x][t]
dp[x][t]为
x
x
x拆分成
t
t
t个数字,且只能是
K
K
K个限制中的。
令
G
d
(
R
,
x
,
y
)
G_d(R,x,y)
Gd(R,x,y)表示走d个非法向量,走到
(
x
,
y
)
(x,y)
(x,y)的方案数。
则:
F
(
d
)
=
∑
x
(
R
d
)
d
p
[
x
]
[
d
]
D
0
(
R
,
T
x
−
x
G
,
T
y
−
x
G
)
F(d)=\sum_{x}\binom{R}{d}dp[x][d]D_0(R,T_x-xG,T_y-xG)
F(d)=x∑(dR)dp[x][d]D0(R,Tx−xG,Ty−xG)
=
∑
t
>
=
d
(
t
d
)
G
t
(
R
,
x
,
y
)
=\sum_{t>=d}\binom{t}{d}G_t(R,x,y)
=t>=d∑(dt)Gt(R,x,y)
二项反演有:
G
d
(
R
,
x
,
y
)
=
∑
d
<
=
n
(
−
1
)
n
−
d
(
n
d
)
F
(
d
)
G_d(R,x,y)=\sum_{d<=n}(-1)^{n-d}\binom{n}{d}F(d)
Gd(R,x,y)=d<=n∑(−1)n−d(dn)F(d)
G
0
(
R
,
x
,
y
)
=
∑
d
<
=
n
(
−
1
)
n
F
(
d
)
G_0(R,x,y)=\sum_{d<=n}(-1)^{n}F(d)
G0(R,x,y)=d<=n∑(−1)nF(d)
简单证一下:
已知:
F
(
n
)
=
∑
t
>
=
n
(
t
n
)
f
(
t
)
F(n) = \sum_{t>=n}\binom{t}{n}f(t)
F(n)=t>=n∑(nt)f(t)
则:
∑
t
>
=
n
(
−
1
)
t
−
n
(
t
n
)
F
(
t
)
=
∑
t
>
=
n
(
−
1
)
t
−
n
(
t
n
)
∑
a
>
=
t
(
a
t
)
f
(
a
)
\sum_{t>=n}(-1)^{t-n}\binom{t}{n}F(t)\\=\sum_{t>=n}(-1)^{t-n}\binom{t}{n}\sum_{a>=t}\binom{a}{t}f(a)
t>=n∑(−1)t−n(nt)F(t)=t>=n∑(−1)t−n(nt)a>=t∑(ta)f(a)
通常情况下,上面和式不发散。则可以交和次序。
∑
a
>
=
n
f
(
a
)
∑
t
=
n
a
(
−
1
)
t
−
n
(
t
n
)
(
a
t
)
\sum_{a>=n}f(a)\sum_{t=n}^{a}(-1)^{t-n}\binom{t}{n}\binom{a}{t}
a>=n∑f(a)t=n∑a(−1)t−n(nt)(ta)
(
t
n
)
(
a
t
)
=
a
!
n
!
(
t
−
n
)
!
(
a
−
t
)
!
=
a
!
(
a
−
n
!
)
!
n
(
a
−
n
)
!
(
t
−
n
)
!
(
a
−
t
)
!
=
(
a
n
)
(
a
−
n
t
−
n
)
\binom{t}{n}\binom{a}{t}=\frac{a!}{n!(t-n)!(a-t)!}\\=\frac{a!(a-n!)}{!n(a-n)!(t-n)!(a-t)!}\\=\binom{a}{n}\binom{a-n}{t-n}
(nt)(ta)=n!(t−n)!(a−t)!a!=!n(a−n)!(t−n)!(a−t)!a!(a−n!)=(na)(t−na−n)
∑
a
>
=
n
f
(
a
)
∑
t
=
n
a
(
−
1
)
t
−
n
(
t
n
)
(
a
t
)
=
∑
a
>
=
n
f
(
a
)
(
a
n
)
∑
t
=
n
a
(
−
1
)
t
−
n
(
a
−
n
t
−
n
)
=
f
(
n
)
\sum_{a>=n}f(a)\sum_{t=n}^{a}(-1)^{t-n}\binom{t}{n}\binom{a}{t}\\=\sum_{a>=n}f(a)\binom{a}{n}\sum_{t=n}^a(-1)^{t-n}\binom{a-n}{t-n}=f(n)
a>=n∑f(a)t=n∑a(−1)t−n(nt)(ta)=a>=n∑f(a)(na)t=n∑a(−1)t−n(t−na−n)=f(n)
所以有: F ( n ) = ∑ t > = n ( t n ) f ( t ) F(n) = \sum_{t>=n}\binom{t}{n}f(t) F(n)=t>=n∑(nt)f(t)可得: f ( n ) = ∑ t > = n ( − 1 ) t − n ( t n ) F ( t ) f(n)=\sum_{t>=n}(-1)^{t-n}\binom{t}{n}F(t) f(n)=t>=n∑(−1)t−n(nt)F(t)
/*
1945555039024054273 = 27*2^56 +1
G = 5
*/
#include <algorithm>
#include <stdio.h>
#include <set>
#include <cmath>
#define MAXN 1000005
#define MAXR 1005
using namespace std;
typedef long long LL;
const int mod = 1e9+7;
const double PI = acos(-1.0);
int P[MAXN];
int Piv[MAXN];
int Mx,My;
void init()
{
P[0] = 1;
P[1] = 1;
Piv[1] = 1;
for(int i = 2; i < MAXN;i++)
{
Piv[i] = mod - (LL)(mod/i)*Piv[mod%i]%mod;
P[i] = LL(P[i-1])*i%mod;
}
for(int i = 2;i < MAXN;i++)Piv[i] = (LL)Piv[i-1]*Piv[i]%mod;
Piv[0] = 1;
}
inline int getC(int a,int b)
{
if(b==0)return 1;
if(a <0)printf("error\n");
if(b < 0|| b > a)return 0;
return ((LL)P[a]*Piv[b]%mod)*Piv[a-b]%mod;
}
int tmpK[60];
int dp[MAXR][1005];
int Ax[MAXR][MAXR];
int Ay[MAXR][MAXR];
int Bx[MAXR][MAXR];
int By[MAXR][MAXR];
void CalculateDp(int B, int R, int k)
{
dp[0][0] = 1;
for(int i = 1;i<R;i++)
{
for(int j = 0;j<B;j++)
{
for(int t = 0;t < k; t++)
{
if(j<tmpK[t])continue;
dp[j][i] +=dp[j-tmpK[t]][i-1];
if(dp[j][i]>=mod)dp[j][i] -=mod;
}
}
}
}
int CalcD(int R,int x,int y)
{
if(R<0)return 0;
int ans = 0;
for(int i=0;i<=R;i++)
{
int u = (LL)getC(R,i)*Ax[R-i][x]%mod;
u = (LL)u*Ay[R-i][y]%mod;
if(i&1)u = (mod - u)%mod;
ans += u;
if(ans >= mod)ans -= mod;
}
return ans;
}
// 5 5 4 4 2 1 3 1 2 3
//5 5 4 4 2 1 2 1 2
int main ()
{
init();
int Tx, Ty, R, G, k;
scanf("%d %d %d %d",&Tx, &Ty, &Mx, &My);
scanf("%d %d", &R, &G);
scanf("%d", &k);
int B = min(Tx,Ty)/G + 1;
for(int i = 0;i<k;i++)
{
scanf("%d",tmpK + i);
tmpK[i] /= G;
}
sort(tmpK, tmpK + k);
B = min(B, tmpK[k-1]*R+1);
for(int i=0;i<=R;i++)
{
for(int x = 0;x< B;x++)
{
int offset = x*G;
for(int a =0,X = Tx - offset ;a <= i;a++)
{
int b = X - (Mx +1)*a;
if(b<0)break;
LL u = (LL)getC(i,a)*getC(i+b-1,b)%mod;
if(a&1) Ax[i][x] += (mod - u)%mod;
else Ax[i][x] += u;
if(Ax[i][x] >=mod)Ax[i][x] -= mod;
}
for(int a=0,Y = Ty - offset;a <=i;a++)
{
int b = Y - (My +1)*a;
if(b<0)break;
LL u = (LL)getC(i,a)*getC(i+b-1,b)%mod;
if(a&1) Ay[i][x] += (mod - u)%mod;
else Ay[i][x] += u;
if(Ay[i][x] >=mod)Ay[i][x] -= mod;
}
}
}
int ans = 0;
if(k == 0)
{
printf("%d\n",CalcD(R,0,0));
return 0;
}
CalculateDp(B,R+1,k);
int limR = min(Tx,Ty)/(tmpK[0]*G) + 1;
//printf("%d ^^^^^\n",CalcD(2,3,3));
for(int d = 0;d< limR;d++)
{
int u = 0;
for(int x = 0;x<B;x++)
{
u += ((LL)getC(R,d)*dp[x][d]%mod)*CalcD(R-d,x,x)%mod;
if(u>=mod)u-=mod;
}
if(d&1)
u = (mod - u)%mod;
ans = (ans + u)%mod;
}
printf("%d\n",ans);
}