zoukankan      html  css  js  c++  java
  • Inna and Binary Logic

    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和相加。想到这里,就可以知道,数的范围是1e5,最多是2^17,所以可以把每个数拆成17位,每一位要么是0或者是1,这样只要统计底层的连续1有多少就可以了。num[i][j]表示第j个数的第i位,一开始我们可以计算出总和,然后更新时,如果更新数的这一位和原来相同则这一位不用变化,否则,如果是1要0,可以把ans先减去原来连续个一所形成的和,然后加上这个数左边连续1的和以及右边连续1的和,然后把这一位变成0,如果是0变1,则相反。这一要注意数据范围,在过程中有可能爆int,所以要用long long,并且在求和过程中使用的局部变量也要用long long,由于自己没有注意到这样的问题结果wa 2发,int和long long之间转换出了问题。也许,有人会问这样会不会t,首先事实上没有t,而且跑的很快。从理论上讲,也不会,因为要出现很长的连续的1是很难的,必须保证这个连续的数在某些位上都是1,并且连续,很难,这样的数据很难。所以很快。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 const int N=1e5+20;
     7 long long num[18][N];
     8 long long ans;
     9 long long a[N],v;
    10 int n,m,p;
    11 long long tmp[18];
    12 int main(){
    13   while(~scanf("%d%d",&n,&m)){
    14       memset(num,0,sizeof(num));
    15       memset(a,0,sizeof(a));
    16       memset(tmp,0,sizeof(tmp));
    17       for(int i=1;i<=n;i++){
    18         scanf("%I64d",&a[i]);
    19         for(int j=0;j<=17;j++){
    20             num[j][i]=(a[i]&1);
    21             a[i]/=2;
    22         }
    23       }
    24        ans=0;
    25       for(int j=0;j<=17;j++){
    26             long long temp=0,tp=0;
    27          for(int i=1;i<=n;i++){
    28             if(num[j][i]==0){
    29                 tp+=temp*(temp+1)/2;
    30                 temp=0;
    31             }
    32             else{
    33                 temp++;
    34             }
    35             if(i==n){
    36                 tp+=temp*(temp+1)/2;
    37                 temp=0;
    38             }
    39          }
    40         ans+=(tp<<j);
    41       }
    42       for(int i=1;i<=m;i++){
    43         scanf("%d%I64d",&p,&v);
    44          for(int j=0;j<=17;j++){
    45              tmp[j]=(v&1);
    46               v/=2;
    47         }
    48         for(int j=0;j<=17;j++){
    49             long long sum=0;
    50             int tt=p;
    51             if(tmp[j]==num[j][p])continue;
    52             long long lnum=0,rnum=0;
    53             while(num[j][--tt])
    54                 lnum++;
    55                 tt=p;
    56             while(num[j][++tt])
    57                 rnum++;
    58             if(tmp[j]==0&&num[j][p]==1){
    59                 sum-=(lnum+rnum+1)*(lnum+rnum+2)/2;
    60                 sum+=(lnum+1)*lnum/2;
    61                 sum+=(rnum+1)*rnum/2;
    62                 num[j][p]=0;
    63             }
    64             else{
    65                 sum-=(lnum+1)*lnum/2;
    66                 sum-=(rnum+1)*rnum/2;
    67                 sum+=(lnum+rnum+1)*(lnum+rnum+2)/2;
    68                 num[j][p]=1;
    69              }
    70            ans+=(sum<<j);
    71         }
    72          printf("%I64d
    ",ans);
    73       }
    74   }
    75 
    76 }
    View Code
  • 相关阅读:
    利用nginx实现负载均衡和动静分离
    Nginx动静分离实现
    php中session 入库的实现
    php文字水印和php图片水印实现代码(二种加水印方法)
    采集图片水印添加
    [安全]PHP能引起安全的函数
    [安全]服务器安全之 PHP权限目录
    Centos下安装git的web服务器
    Centos下抓包
    UVA 10795
  • 原文地址:https://www.cnblogs.com/chujian123/p/3887553.html
Copyright © 2011-2022 走看看