洛谷 P8367 [LNOI2022] 盒 题解

考虑给定 a , b a,b a,b 时怎么做。显然:

a n s = ∑ i = 1 n − 1 w i ∣ ∑ j = 1 i a j − ∑ j = 1 i b j ∣ ans=\sum_{i=1}^{n-1}w_i\Bigg|\sum_{j=1}^ia_j-\sum_{j=1}^ib_j\Bigg| ans=i=1n1wi j=1iajj=1ibj

因此,若设 c i , d i c_i,d_i ci,di 分别为 a i , b i a_i,b_i ai,bi 的前缀和,答案即为 ∑ d ∑ i = 1 n − 1 w i ∣ c i − d i ∣ \sum\limits_ d\sum\limits_{i=1}^{n-1}w_i|c_i-d_i| di=1n1wicidi

由于 i i i 确定时, c i c_i ci 是确定的,考虑枚举 d i d_i di 并统计可能的方案数,即 ∑ i = 1 n − 1 w i ∑ d i = 0 S ∣ c i − d i ∣ × cnt ( i , d i ) \sum\limits_{i=1}^{n-1}w_i\sum\limits_{d_i=0}^S|c_i-d_i|\times \text{cnt}(i,d_i) i=1n1widi=0Scidi×cnt(i,di),其中 cnt ( i , d i ) \text{cnt}(i,d_i) cnt(i,di) 即为方案数。

考虑对 d d d 数列进行分析。由于 b b b 数列均为非负整数,则 d d d 数列单调不降且 d 0 = 0 , d n = S d_0=0,d_n=S d0=0,dn=S

0 ≤ d 1 ≤ d 2 ≤ ⋯ ≤ d i ≤ d i + 1 ≤ ⋯ ≤ d n = S 0\le d_1\le d_2\le\cdots\le d_i\le d_{i+1}\le\cdots\le d_n=S 0d1d2didi+1dn=S,可分为 [ 1 , i ) [1,i) [1,i) ( i , n ) (i,n) (i,n) 考虑,接下来以求 0 ≤ d 1 ≤ d 2 ≤ ⋯ ≤ d i 0\le d_1\le d_2\le\cdots\le d_i 0d1d2di 的解的个数为例。

若为小于号,可以通过组合数轻松求出,因此我们可设 d i ′ = d i + i d'_i=d_i+i di=di+i,则只需求解 0 < d 1 ′ < ⋯ < d i − 1 ′ < d i ′ 0<d'_1<\cdots<d'_{i-1}<d'_i 0<d1<<di1<di 的个数,方案数为 d i ′ − 1 d'_i-1 di1 个空位选 i − 1 i-1 i1 个数,即 ( d i ′ − 1 i − 1 ) = ( d i + i − 1 i − 1 ) \binom{d'_i-1}{i-1}=\binom{d_i+i-1}{i-1} (i1di1)=(i1di+i1),同理右侧方案数为 ( S + n − d i − i − 1 n − i − 1 ) \binom{S+n-d_i-i-1}{n-i-1} (ni1S+ndii1),因此代换掉 cnt ( i , d i ) \text{cnt}(i,d_i) cnt(i,di) 可得:

a n s = ∑ i = 1 n − 1 w i ( ∑ d i = 0 S ∣ c i − d i ∣ × ( d i + i − 1 i − 1 ) × ( S − d i + n − i − 1 n − i − 1 ) ) = ∑ i = 1 n − 1 w i ( 2 ∑ d i = 0 c i ( c i − d i ) × ( d i + i − 1 i − 1 ) × ( S − d i + n − i − 1 n − i − 1 ) + ∑ d i = 0 S ( d i − c i ) × ( d i + i − 1 i − 1 ) × ( S − d i + n − i − 1 n − i − 1 ) ) \begin{aligned} ans&=\sum_{i=1}^{n-1}w_i\Bigg(\sum_{d_i=0}^S|c_i-d_i|\times\binom{d_i+i-1}{i-1}\times \binom{S-d_i+n-i-1}{n-i-1}\Bigg)\\ &=\sum_{i=1}^{n-1}w_i\Bigg(2\sum_{d_i=0}^{c_i}(c_i-d_i)\times\binom{d_i+i-1}{i-1}\times\binom{S-d_i+n-i-1}{n-i-1}+\sum_{d_i=0}^S(d_i-c_i)\times \binom{d_i+i-1}{i-1}\times\binom{S-d_i+n-i-1}{n-i-1}\Bigg)\\ \end{aligned} ans=i=1n1wi(di=0Scidi×(i1di+i1)×(ni1Sdi+ni1))=i=1n1wi(2di=0ci(cidi)×(i1di+i1)×(ni1Sdi+ni1)+di=0S(dici)×(i1di+i1)×(ni1Sdi+ni1))

设:

f ( n , S , i , k ) = ∑ d i = 0 k ( d i + i − 1 i − 1 ) × ( S − d i + n − i − 1 n − i − 1 ) f(n,S,i,k)=\sum_{d_i=0}^k \binom{d_i+i-1}{i-1}\times\binom{S-d_i+n-i-1}{n-i-1} f(n,S,i,k)=di=0k(i1di+i1)×(ni1Sdi+ni1)

g ( n , S , i , k ) = ∑ d i = 0 k d i × ( d i + i − 1 i − 1 ) × ( S − d i + n − i − 1 n − i − 1 ) g(n,S,i,k)=\sum_{d_i=0}^kd_i\times \binom{d_i+i-1}{i-1}\times\binom{S-d_i+n-i-1}{n-i-1} g(n,S,i,k)=di=0kdi×(i1di+i1)×(ni1Sdi+ni1)

则原式等价于:

∑ i = 1 n − 1 w i ( 2 c i × f ( n , S , i , c i ) − 2 g ( n , S , i , c i ) + g ( n , S , i , S ) − c i × f ( n , S , i , S ) ) \sum_{i=1}^{n-1}w_i\Bigg(2c_i\times f(n,S,i,c_i)-2g(n,S,i,c_i)+g(n,S,i,S)-c_i\times f(n,S,i,S)\Bigg) i=1n1wi(2ci×f(n,S,i,ci)2g(n,S,i,ci)+g(n,S,i,S)ci×f(n,S,i,S))

考虑探究 g g g f f f 的关系:

g ( n , S , i , k ) = ∑ d i = 0 k d i × ( d i + i − 1 i − 1 ) × ( S − d i + n − i − 1 n − i − 1 ) = ∑ d i = 1 k d i × ( d i + i − 1 d i ) × ( S − d i + n − i − 1 n − i − 1 ) = i × ∑ d i = 1 k ( d i + i − 1 i ) × ( S − d i + n − i − 1 n − i − 1 ) \begin{aligned} g(n,S,i,k)&=\sum_{d_i=0}^kd_i\times \binom{d_i+i-1}{i-1}\times\binom{S-d_i+n-i-1}{n-i-1}\\ &=\sum_{d_i=1}^kd_i\times \binom{d_i+i-1}{d_i}\times\binom{S-d_i+n-i-1}{n-i-1}\\ &=i\times\sum_{d_i=1}^k\binom{d_i+i-1}{i}\times\binom{S-d_i+n-i-1}{n-i-1}\\ \end{aligned} g(n,S,i,k)=di=0kdi×(i1di+i1)×(ni1Sdi+ni1)=di=1kdi×(didi+i1)×(ni1Sdi+ni1)=i×di=1k(idi+i1)×(ni1Sdi+ni1)

由于左侧的 i i i i − 1 i-1 i1 不同,不符合 f f f 的形式,考虑 d i ← d i − 1 d_i\leftarrow d_i-1 didi1 得:

g ( n , S , i , k ) = i × ∑ d i = 0 k − 1 ( d i + i i ) × ( S − d i + n − i − 2 n − i − 1 ) = i × f ( n + 1 , S − 1 , i + 1 , k − 1 ) \begin{aligned} g(n,S,i,k)&=i\times\sum_{d_i=0}^{k-1}\binom{d_i+i}{i}\times\binom{S-d_i+n-i-2}{n-i-1}\\ &=i\times f(n+1,S-1,i+1,k-1)\\ \end{aligned} g(n,S,i,k)=i×di=0k1(idi+i)×(ni1Sdi+ni2)=i×f(n+1,S1,i+1,k1)

由于暴力计算 f ( n , S , i , k ) f(n,S,i,k) f(n,S,i,k) 显然不优,考虑增量计算。

即需得出 f ( n , S , i , k ) → f ( n , S , i + 1 , k ) f(n,S,i,k)\to f(n,S,i+1,k) f(n,S,i,k)f(n,S,i+1,k) f ( n , S , i , k ) → f ( n , S , i , k + 1 ) f(n,S,i,k)\to f(n,S,i,k+1) f(n,S,i,k)f(n,S,i,k+1) 的关系式。

后者显然:

f ( n , S , i , k + 1 ) = f ( n , S , i , k ) + ( k + i i − 1 ) × ( S − k + n − i − 2 n − i − 1 ) f(n,S,i,k+1)=f(n,S,i,k)+\binom{k+i}{i-1}\times\binom{S-k+n-i-2}{n-i-1} f(n,S,i,k+1)=f(n,S,i,k)+(i1k+i)×(ni1Sk+ni2)

前者考虑对 f ( n , S , i , k ) f(n,S,i,k) f(n,S,i,k) 的组合意义进行分析。

f ( n , S , i , k ) f(n,S,i,k) f(n,S,i,k) 即为 ( 0 , 0 ) → ( i − 1 , d i ) → ( i , d i ) → ( n − 1 , S ) (0,0)\to(i-1,d_i)\to(i,d_i)\to(n-1,S) (0,0)(i1,di)(i,di)(n1,S) 的方案数。

而由于 d i ∈ [ 0 , k ] d_i\in[0,k] di[0,k],说明从第 k k k 行走向第 k + 1 k+1 k+1 行时的横坐标必然大于 i − 1 i-1 i1

于是 f ( n , S , i , k ) f(n,S,i,k) f(n,S,i,k) 即为 ( 0 , 0 ) → ( j , k ) → ( j , k + 1 ) → ( n − 1 , S ) (0,0)\to(j,k)\to(j,k+1)\to(n-1,S) (0,0)(j,k)(j,k+1)(n1,S) 的方案数,其中 j ∈ [ i , n ] j\in[i,n] j[i,n],因此:

f ( n , S , i , k ) = ∑ j = i n ( j + k j ) × ( n + S − j − k − 2 S − k − 1 ) f(n,S,i,k)=\sum_{j=i}^n\binom{j+k}{j}\times\binom{n+S-j-k-2}{S-k-1} f(n,S,i,k)=j=in(jj+k)×(Sk1n+Sjk2)

则:

f ( n , S , i + 1 , k ) = f ( n , S , i , k ) − ( i + k i ) × ( n + S − i − k − 2 S − k − 1 ) f(n,S,i+1,k)=f(n,S,i,k)-\binom{i+k}{i}\times\binom{n+S-i-k-2}{S-k-1} f(n,S,i+1,k)=f(n,S,i,k)(ii+k)×(Sk1n+Sik2)

回到原式:

a n s = ∑ i = 1 n − 1 w i ( 2 c i × f ( n , S , i , c i ) − 2 i × f ( n + 1 , S − 1 , i + 1 , c i − 1 ) + i × f ( n + 1 , S − 1 , i + 1 , S − 1 ) − c i × f ( n , S , i , S ) ) = ∑ i = 1 n − 1 w i ( c i × ( 2 f ( n , S , i , c i ) − f ( n , S , i , S ) ) + i × ( f ( n + 1 , S − 1 , i + 1 , S − 1 ) − 2 f ( n + 1 , S − 1 , i + 1 , c i − 1 ) ) ) \begin{aligned} ans&=\sum_{i=1}^{n-1}w_i\Bigg(2c_i\times f(n,S,i,c_i)-2i\times f(n+1,S-1,i+1,c_i-1)+i\times f(n+1,S-1,i+1,S-1)-c_i\times f(n,S,i,S)\Bigg)\\ &=\sum_{i=1}^{n-1}w_i\Bigg(c_i\times\Big(2f(n,S,i,c_i)-f(n,S,i,S)\Big)+i\times\Big(f(n+1,S-1,i+1,S-1)-2f(n+1,S-1,i+1,c_i-1)\Big)\Bigg)\\ \end{aligned} ans=i=1n1wi(2ci×f(n,S,i,ci)2i×f(n+1,S1,i+1,ci1)+i×f(n+1,S1,i+1,S1)ci×f(n,S,i,S))=i=1n1wi(ci×(2f(n,S,i,ci)f(n,S,i,S))+i×(f(n+1,S1,i+1,S1)2f(n+1,S1,i+1,ci1)))

由于 i , c i i,c_i i,ci 单调不降,直接增量维护四个不同的 f f f 即可。

#include <bits/stdc++.h>
using namespace std;
const int p=998244353;
long long T,n,S,a[500005],w[500005],fac[3000005],ifac[3000005],c[500005];
inline long long qpow(long long a,long long b){
	int res=1;
	for (;b;b>>=1,a=1ll*a*a%p) if (b&1) res=1ll*res*a%p;
	return res;
}
inline long long C(long long n,long long m){
	return fac[n]*ifac[m]%p*ifac[n-m]%p;
}
struct f{
	long long n,S,i,k,res;
	void init(long long n0,long long S0,long long i0,long long k0){
		n=n0,S=S0,i=i0,k=k0,res=0;
    	for (long long di=0;di<=k;di++) (res+=1ll*C(di+i-1,i-1)*C(S-di+n-i-1,n-i-1)%p)%=p;
	}
	void movek(long long K){
		if (k>=K) return;
		for (;k<K;k++) res+=C(k+i,i-1)*C(S-k+n-i-2,n-i-1)%p;
		res%=p;
	}
	void movei(long long I){
		if (i>=I) return;
		for (;i<I;i++) res+=p-C(i+k,i)*C(n+S-i-k-2,S-k-1)%p;
		res%=p;
	}
}f1,f2,f3,f4;
int main(){
	scanf("%lld",&T);
	fac[0]=1;
	for (int i=1;i<=3e6;i++) fac[i]=fac[i-1]*i%p;
	ifac[3000000]=qpow(fac[3000000],p-2);
	for (int i=3e6-1;i>=0;i--) ifac[i]=ifac[i+1]*(i+1)%p;
	while (T--){
		scanf("%lld",&n),S=0;
		for (int i=1;i<=n;i++) scanf("%lld",&a[i]),S+=a[i],c[i]=c[i-1]+a[i];
		for (int i=1;i<n;i++) scanf("%lld",&w[i]);
		long long ans=0;
		f1.init(n,S,1,c[1]),f2.init(n,S,1,S),f3.init(n+1,S-1,2,S-1),f4.init(n+1,S-1,2,c[1]-1);
		for (int i=1;i<n;i++){
			f1.movei(i),f2.movei(i),f3.movei(i+1),f4.movei(i+1);
			f1.movek(c[i]),f4.movek(c[i]-1);
		    (ans+=w[i]*(c[i]*(2*f1.res-f2.res+p)%p+i*(f3.res-2*f4.res+p)%p))%=p;
		}
		printf("%lld\n",(ans+p)%p);
	}
	return 0;
}
  • 9
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于洛谷上的p1036题目,我们可以使用Python来解决。下面是一个可能的解法: ```python def dfs(nums, target, selected_nums, index, k, sum): if k == 0 and sum == target: return 1 if index >= len(nums) or k <= 0 or sum > target: return 0 count = 0 for i in range(index, len(nums)): count += dfs(nums, target, selected_nums + [nums[i]], i + 1, k - 1, sum + nums[i]) return count if __name__ == "__main__": n, k = map(int, input().split()) nums = list(map(int, input().split())) target = int(input()) print(dfs(nums, target, [], 0, k, 0)) ``` 在这个解法中,我们使用了深度优先搜索(DFS)来找到满足要求的数列。通过递归的方式,我们遍历了所有可能的数字组合,并统计满足条件的个数。 首先,我们从给定的n和k分别表示数字个数和需要选取的数字个数。然后,我们输入n个数字,并将它们存储在一个列表nums中。接下来,我们输入目标值target。 在dfs函数中,我们通过迭代index来选择数字,并更新选取的数字个数k和当前总和sum。如果k等于0且sum等于target,我们就找到了一个满足条件的组合,返回1。如果index超出了列表长度或者k小于等于0或者sum大于target,说明当前组合不满足要求,返回0。 在循环中,我们不断递归调用dfs函数,将选取的数字添加到selected_nums中,并将index和k更新为下一轮递归所需的值。最终,我们返回所有满足条件的组合个数。 最后,我们在主程序中读入输入,并调用dfs函数,并输出结果。 这是一种可能的解法,但不一定是最优解。你可以根据题目要求和测试数据进行调试和优化。希望能对你有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值