您的位置:首页 > 其它

Inna and Binary Logic

2014-08-02 22:20 344 查看
Codeforces Round #234 (Div. 2) E:http://codeforces.com/problemset/problem/400/E

题意:给你n个数,然后每相邻的两个数可以通过and运算生成一个新的数,然后这些新生成的n-1个数每相邻的两个数又通过and运算成n-2个数,最后只会剩下一个数,然后让你求这n(n+1)/2个数的和,然后每一次会更新最底层的某个数,然后操作之后,输出刚才的总和。

题解:这一题,虽然是看题解,然后自己敲出来的,但是还是有点成就感和收获。首先,这一题的思路很巧妙。如果所有的数都是1或者0,加入说序列是1110001,通过计算,发现其实和就是(3+1)*3/2+(1+1)*1/2==7,与连续1的个数有关,加入连续1的个数是x,那么这连续的x个1,形成的和就是(x+1)*x/2;总和就是把所有连续的1和相加。想到这里,就可以知道,数的范围是1

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+20;
long long num[18]
;
long long ans;
long long a
,v;
int n,m,p;
long long tmp[18];
int main(){
while(~scanf("%d%d",&n,&m)){
memset(num,0,sizeof(num));
memset(a,0,sizeof(a));
memset(tmp,0,sizeof(tmp));
for(int i=1;i<=n;i++){
scanf("%I64d",&a[i]);
for(int j=0;j<=17;j++){
num[j][i]=(a[i]&1);
a[i]/=2;
}
}
ans=0;
for(int j=0;j<=17;j++){
long long temp=0,tp=0;
for(int i=1;i<=n;i++){
if(num[j][i]==0){
tp+=temp*(temp+1)/2;
temp=0;
}
else{
temp++;
}
if(i==n){
tp+=temp*(temp+1)/2;
temp=0;
}
}
ans+=(tp<<j);
}
for(int i=1;i<=m;i++){
scanf("%d%I64d",&p,&v);
for(int j=0;j<=17;j++){
tmp[j]=(v&1);
v/=2;
}
for(int j=0;j<=17;j++){
long long sum=0;
int tt=p;
if(tmp[j]==num[j][p])continue;
long long lnum=0,rnum=0;
while(num[j][--tt])
lnum++;
tt=p;
while(num[j][++tt])
rnum++;
if(tmp[j]==0&&num[j][p]==1){
sum-=(lnum+rnum+1)*(lnum+rnum+2)/2;
sum+=(lnum+1)*lnum/2;
sum+=(rnum+1)*rnum/2;
num[j][p]=0;
}
else{
sum-=(lnum+1)*lnum/2;
sum-=(rnum+1)*rnum/2;
sum+=(lnum+rnum+1)*(lnum+rnum+2)/2;
num[j][p]=1;
}
ans+=(sum<<j);
}
printf("%I64d\n",ans);
}
}

}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: