zoukankan      html  css  js  c++  java
  • cdoj第13th校赛初赛H

    http://acm.uestc.edu.cn/#/contest/show/54

    H - Hug the princess

    Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
     

    There is a sequence with n elements. Assuming they are a1,a2,⋯,an.
    Please calculate the following expession.

    In the expression above, ^ | & is bit operation.

    Input

    The first line contains a single integer n, which is the size of the sequence.

    The second line contains n integers, the ith integer ai is the ith element of the sequence.

    1n100000,0ai100000000

    Output

    Print the answer in one line.

    Sample input and output

    Sample InputSample Output
    2
    1 2
    6

    思路:首先,自己可以通过举几个例子来验证,异或运算与与运算之和刚好等价于或运算,或者可以这样想,异或是(1,0)、(0,1),与是(1,1),合起来刚好是或。然后题目就是求两倍的或运算了。然后,每一个ai都与aj或运算(i<j),每次ai与aj或的时候,aj二进制位上是1的数位在或运算后总还是1,所以前面有多个ai与aj或,最后结果里就有多少个aj的和;然后考虑aj上是0的数位(比如第4位),记录前面所有的ai中哪些数在这个第4位上是1,记为sum[4],最后的结果里就有sum[4]*(1<<4),因为有权值的嘛。这样O(n)地扫一遍,就行了。如果就像我第一次那样直接O(n*n)地把所有数进行或运算,呵呵,tle了。

    这是官方题解:

    代码:

     1 #include <fstream>
     2 #include <iostream>
     3 #include <algorithm>
     4 #include <cstdio>
     5 #include <cstring>
     6 #include <cmath>
     7 #include <cstdlib>
     8 #include <vector>
     9 
    10 using namespace std;
    11 
    12 #define PI acos(-1.0)
    13 #define EPS 1e-10
    14 #define lll __int64
    15 #define ll long long
    16 #define INF 0x7fffffff
    17 
    18 ll a[100005];
    19 vector<ll> cnt;
    20 
    21 int main(){
    22     //freopen("D:\input.in","r",stdin);
    23     //freopen("D:\output.out","w",stdout);
    24     int n;
    25     ll tn=0;
    26     scanf("%d",&n);
    27     for(int i=0;i<n;i++){
    28         scanf("%lld",&a[i]);
    29         tn=max(tn,a[i]);
    30     }
    31     ll ans=0,t=0;
    32     while(tn){
    33         t++;
    34         tn>>=1;
    35         cnt.push_back(0);
    36     }
    37     for(int i=0;i<n;i++){
    38         ans+=a[i]*i;
    39         for(int j=0;j<t;j++){
    40             if(!((a[i]>>j)&1)){
    41                 ans+=(1<<j)*cnt[j];
    42             }else{
    43                 cnt[j]++;
    44             }
    45         }
    46     }
    47     printf("%lld
    ",ans*2);
    48     return 0;
    49 }
    View Code
  • 相关阅读:
    poj 1113 wall(凸包裸题)(记住求线段距离的时候是点积,点积是cos)
    Atcoder(134)E
    poj 1696 极角排序(解题报告)
    poj 1410 (没做出来,记得闲着没事看看这道题)
    poj1066 线段相交简单应用(解题报告)
    poj 2653 线段相交裸题(解题报告)
    poj 1269
    要习惯用vector代替数组
    在 Angularjs 中$state.go 如何传递参数
    CSS实现内容超过长度后以省略号显示
  • 原文地址:https://www.cnblogs.com/jiu0821/p/4378910.html
Copyright © 2011-2022 走看看