「SDWC2018 Day1」网格

Address

LOJ#6374

Solution

题目给出 3 3 3 个限制:

  1. x ≤ x ′ ≤ x + M x , y ≤ y ′ ≤ y + M y x\leq x'\leq x+M_x , y\leq y'\leq y+M_y xxx+Mx,yyy+My
  2. 每一步都不能停在原地
  3. 每一步 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 xxx+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×CTxi(Mx+1)+R1R1。显然每个 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)ji×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=iR(1)ji×Cji×g(j)=j=iR(1)ji×Cji×k=jR×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=iR(j=ik(1)ji×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)ji×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=ik(1)ji×Cji×Ckj=Ckij=ik(1)ji×Ckiji=Ckij=0ki(1)j×Ckij 发现只有在 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=iR(j=ik(1)ji×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=0R(1)i0×Ci0×g(i)=i=0R(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 ij 步停在原地,那么有:
p ( i ) = ∑ j = 0 i C i j × h ( j ) p(i)=\sum_{j=0}^iC_i^j×h(j) p(i)=j=0iCij×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=0i(1)Ri×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 xxx+Mx,yyy+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)=jS(i,j)×calc(TxjG,TyjG,Mx,My,Rj)×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=iRCji×b(j) 同样反演可得 b ( 0 ) = ∑ i = 0 R ( − 1 ) i a ( i ) b(0)=\sum_{i=0}^R(-1)^ia(i) b(0)=i=0R(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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值