51nod2383
2383 高维部分和
- 1 秒
- 131,072 KB
- 80 分
- 5 级题
输入一个长度为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];
}
}
}
第二份代码就不一定更慢了(第二份复杂度大约3n^3,第一份复杂度大概8n^3)
随着维度更高,第一份代码容斥时项数越来越多,而第二份只是多一次遍历整个数组,优势越来越大。
同样的思路能不能推广到更高维的情况呢?
收起
输入
第一行一个整数n
接下来n行n个整数,表示a[i]
输出
输出共n行,其中第i(0 <= i < n)行表示i的答案。
输入样例
8
1
2
4
8
16
32
64
128
输出样例
1
3
5
15
17
51
85
255 sol:表示只要找找规律就行了(假)
大概像是前缀和一样呗,对于每一位,加上异或那位的值就可以了,这样是不会重复的,
#include <bits/stdc++.h>
using namespace std;
typedef int ll;
inline ll read()
{
ll s=;
bool f=;
char ch=' ';
while(!isdigit(ch))
{
f|=(ch=='-'); ch=getchar();
}
while(isdigit(ch))
{
s=(s<<)+(s<<)+(ch^); ch=getchar();
}
return (f)?(-s):(s);
}
#define R(x) x=read()
inline void write(ll x)
{
if(x<)
{
putchar('-'); x=-x;
}
if(x<)
{
putchar(x+''); return;
}
write(x/);
putchar((x%)+'');
return;
}
#define W(x) write(x),putchar(' ')
#define Wl(x) write(x),putchar('\n')
const int N=;
int n,a[N];
int main()
{
freopen("std.in","r",stdin);
freopen("std.out","w",stdout);
int i,j;
R(n);
for(i=;i<n;i++) R(a[i]);
for(j=;j<=n;j<<=)
{
for(i=;i<n;i++) if((i&j)==j)
{
a[i]+=a[i^j];
}
}
for(i=;i<n;i++) Wl(a[i]);
return ;
}
/*
input
8
1
2
4
8
16
32
64
128
output
1
3
5
15
17
51
85
255
*/
51nod2383的更多相关文章
随机推荐
- 【LOJ 2145】「SHOI2017」分手是祝愿
LOJ 2145 100pts 这题...BT啊 首先我们很容易想出\(dp(msk)\)表示现在灯开关的情况是\(msk\),期望通过多少步走到终结态. 很明显\(dp(msk)=\frac{1}{ ...
- 【原创】三招搞死你的IE11,可重现代码下载(IE Crash keyframes iframe)!
前言 很多人都知道我们在做FineUI控件库,而且我们也做了超过 9 年的时间,在和浏览器无数次的交往中,也发现了多个浏览器自身的BUG,并公开出来方便大家查阅: 分享IE7一个神奇的BUG(不是封闭 ...
- Java之所有输入流输出流的分类
(1)字节输入流 基类:InputStream FileInputStream.ByteArrayInputStream.PipedInputStream.Buffered ...
- 【Python撩妹合集】微信聊天机器人,推送天气早报、睡前故事、精美图片分享
福利时间,福利时间,福利时间 如果你还在为不知道怎么撩妹而烦恼,不知道怎么勾搭小仙女而困惑,又或者不知道怎么讨女朋友欢心而长吁短叹. 那么不要犹豫徘徊,往下看.接下来我会分享怎么使用 Python 实 ...
- 个人实战演练全过程——No.1 最大连续子数组求和
之前的一次个人总结和一次单元测试入门学习是开启软件工程课程的前奏曲,也是热身,现在大家对于这门课程也有了初步的了解和认识,这次要开始真正的演奏了,要从头到尾完全靠自己的能力来解决一个问题,进行实战演练 ...
- xadmin集成DjangoUeditor
1.安装 安装DjangoUeditor 1)去GitHub上面下载djangoueditor源码包(https://github.com/twz915/DjangoUeditor3) 然后进入源 ...
- 第十五次oo作业
作业十五 测试与正确性论证的效果差异 程序的测试需要通过输入特定数据等方式,检查程序是否和预期相同,因为测试不可能穷举,导致了不穷举的测试不可能验证程序是完全正确的,只能验证程序在测试时没有发生错误, ...
- Diverse Garland CodeForces - 1108D (贪心+暴力枚举)
You have a garland consisting of nn lamps. Each lamp is colored red, green or blue. The color of the ...
- openstack-KVM管理工具
一. virsh 通过libvirt API管理Hpervisor.node.domain,实现多数功能调用. 即统一管理多台计算机上的域. 1.管理其他服务器(node) (1)修改配置文件:vim ...
- 【学习总结】Git学习-参考廖雪峰老师教程十-自定义Git
学习总结之Git学习-总 目录: 一.Git简介 二.安装Git 三.创建版本库 四.时光机穿梭 五.远程仓库 六.分支管理 七.标签管理 八.使用GitHub 九.使用码云 十.自定义Git 期末总 ...