部分和

版权声明:未经过同意不得转载 https://blog.csdn.net/qq_42500298/article/details/82954286

题目描述

输入一个长度为n的数组a[i],下标从0开始(0到n-1) 保证n是2的整数次幂, 对于每个i (0 <= i < n) 求所有满足((i & j) == j)的a[j]之和。
其中&表示按位与,即C++和C中的&,Pascal中的and。
对于100%的数据,1 <= n <= 220, 0 <= a[i] <= 1000
对于70%的数据,1 <= n <= 215,
对于50%的数据,1 <= n <= 210,

虽然这是一个简单题,但是为了降低难度,你可以看看下面的解释。

对于一个一维数组求部分和,可以使用如下代码

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

对于一个二维数组求部分和,可以使用如下代码

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

或如下代码

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]     
	}
}

第二份代码看起来更麻烦更慢,来考虑一下三维的情况。

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] + a[i][j - 1][k] + a[i - 1][j][k];             
			a[i][j][k] -= a[i][j - 1][k - 1] + a[i - 1][j - 1][k] + a[i - 1][j][k - 1];             
			a[i][j][k] += a[i - 1][j - 1][k - 1];         
		}     
	} 
} 

或如下代码

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];         
		}     
	}
} 
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 - 1][j][k];        
		}     
	}
} 

第二份代码就不一定更慢了(第二份复杂度大约3* n 3 n^3 ,第一份复杂度大概8* n 3 n^3 ) 随着维度更高,第一份代码容斥时项数越来越多,而第二份只是多一次遍历整个数组,优势越来越大。 同样的思路能不能推广到更高维的情况呢?

输入描述:

第一行一个整数n接下来n行n个整数,表示a[i]

输出描述:

输出共n行,其中第i(0 <= i < n)行表示i的答案。

示例1

输入

8
1
2
4
8
16
32
64
128

输出

1
3
5
15
17
51
85
255

说明

i=0的答案 a[0]
i=1的答案 a[0] + a[1]
i=2的答案 a[0] + a[2]
i=3的答案 a[0] + a[1] + a[2] + a[3]
i=4的答案 a[0] + a[4]
i=5的答案 a[0] + a[1] + a[4] + a[5]
i=6的答案 a[0] + a[2] + a[4] + a[6]
i=7的答案 a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7]

#include<bits/stdc++.h>
using namespace std;
int i,m,n,j,k,a[2000001],g;
inline int gtt()
{
	char c=getchar();
	int x=0,r=1;
	while(c<'0'||c>'9') 
	{
		if(c=='-') 
			r=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9')
		x=(x<<3)+(x<<1)+c-48,c=getchar();
	return x*r;
}
inline void ptt(int a)
{
	int u[15]; u[0]=0;
	while(a)
	{
		u[++u[0]]=a%10;
		a/=10;
	}
	for(register int i=u[0];i>=1;i--) 
		putchar(u[i]+'0');
	putchar('\n');
}
int main()
{
	scanf("%d",&n);
	for(register int i=0;i<n;i++) 
		a[i]=gtt();
	m=n; 
	g=0; 
	while(m)
	{
		m>>=1;
		g+=1;
	}
	for(register int i=0;i<g;i++) 
	{
		for(register int j=(1<<i);j<n;j++)
		{
			if(j&(1<<i)) 
			a[j]+=a[j-(1<<i)];
		}
	}
	for(register int i=0;i<n;i++) 
		ptt(a[i]);
	return 0; 
}

来源:nkw

猜你喜欢

转载自blog.csdn.net/qq_42500298/article/details/82954286