高维前缀和

  • 给定 n,qf(0),f(1),,f(2n1)q 次询问,给定 S,求:

    SSf(S)

  • n20q106

Si 表示 S 的第 i 个二进制位。

可以发现若 SS,那么对于所有 i 都有 SiSi。也就是要求:

S0=0S0S1=0S1S2=0S2,Sn1=0Sn1f(S)

发现这就是一个 n 维的前缀和的形式。

对于二维前缀和,除朴素的容斥做法 si,j=si,j1+si1,jsi1,j1+ai,j 外,可以用这种方式:

for (int i = 1; i <= n; ++ i )
	for (int j = 1; j <= n; ++ j )
		a[i][j] += a[i][j - 1];
for (int i = 1; i <= n; ++ i )
	for (int j = 1; j <= n; ++ j )
		a[i][j] += a[i - 1][j];

第一个循环后,ai,j=ai,1+ai,2++ai,j,表示先对每行单独做一遍前缀和。

第二个循环后,ai,j 就是真正的左上矩阵的和,此时是对每列单独做一遍前缀和。

同理可以延伸到三维:

for (int i = 1; i <= n; ++ i )
	for (int j = 1; j <= n; ++ j )
		for (int k = 1; k <= n; ++ k )
			a[i][j][k] += a[i - 1][j][k];
for (int i = 1; i <= n; ++ i )
	for (int j = 1; j <= n; ++ j )
		for (int k = 1; k <= n; ++ k )
			a[i][j][k] += a[i][j - 1][k];
for (int i = 1; i <= n; ++ i )
	for (int j = 1; j <= n; ++ j )
		for (int k = 1; k <= n; ++ k )
			a[i][j][k] += a[i][j][k - 1];

枚举范围为 [0,1] 时就可以用位运算计算了。

我们令答案式为 g(S)。类比上边两份代码,可以得到:

for (int j = 0; j < n; ++ j )
    for (int i = 0; i < (1 << n); ++ i )
		if (i >> j & 1)
			g[i] += g[i ^ (1 << j)];

例题:CF1234F Yet Another Substring Reverse

posted @   2huk  阅读(34)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示