题目描述
输入一个长度为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* ,第一份复杂度大概8* ) 随着维度更高,第一份代码容斥时项数越来越多,而第二份只是多一次遍历整个数组,优势越来越大。 同样的思路能不能推广到更高维的情况呢?
输入描述:
第一行一个整数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