• ZZULIOJ Problem 1893: 985的数学难题 【位运算】


    1893: 985的数学难题

    Time Limit: 2 Sec  Memory Limit: 128 MB
    Submit: 161  Solved: 37

    Description

    985有n个正整数,他想快速知道下面函数的返回值
     
    int a[N+1];
    long long Solve() {
        int i, j;
        long long ans = 0;
        for(i = 1; i <= N; i++) {
        for(int j = i + 1; j <= N; j++) {
        ans += a[i] + a[j] + (a[i] ^ a[j]) + (a[i] | a[j]) + (a[i] & a[j]);
    }
        }
        return ans;
    }
     
    注:^表示异或运算。

    Input

    第一行输入一个整数t,代表有t组测试数据。
    每组数据第一行输入一个整数代表元素个数,接下来一行输入n个正整数a[]。
    注:1 <= t <= 30,1 <= n,a[] <= 100000。
     

    Output

    一个整数代表最后的返回值ans。

    Sample Input

    2
    1
    10
    2
    1 1

    Sample Output

    0
    4

    HINT

     

    Source

    hpu

    郁闷,各种对拍,随机数,自己写数据,都和暴力的没有区别,就是WA,结果数组改为long long 就过了……

    思路:用sum[i][j]表示到第i个数有多少个数二进制的j位置上为零。a|b = a^b + a&b,所以只要统计a|b就可以了。对于 A i | A (i+1) + Ai | A(i+2) +  …… + Ai | A(n),只需要统计每一位的贡献,就可以,嘴笨,看代码。

    #include <cstdio>
    #include <algorithm>
    #define MAXN 100005
    using namespace std;
    long long ar[MAXN], sum[MAXN][65];
    int judge(long long x, int y) {
        if (x & (1<<y)) return 1;
        return 0;
    }
    int main() {
        int t = 1, n; scanf("%d", &t);
       // freopen("data.txt", "r", stdin);
        //freopen("2.txt", "w", stdout);
        while (t--) {
            scanf("%d", &n); long long ans = 0;
           // printf("%d ", n);
            for (int i = 0; i <= 17; i++) sum[0][i] = 0;
            for (int i = 1; i <= n; i++) {
                scanf("%lld", &ar[i]);
               // printf("%d ", ar[i]);
                for (int j = 0; j <= 17; j++) {
                    sum[i][j] = sum[i-1][j] + judge(ar[i], j);
                }
                ans += (n - 1)*ar[i];
            }
            // bit operator of '|'
            for (int i = 1; i <= n; i++) {
                for (int j = 0; j <= 17; j++) {
                    long long num1 = sum[n][j] - sum[i][j];
                    long long num0 = n - i;
                    if (ar[i] & (1<<j)) ans += (1<<j)*num0*2;
                    else ans += (1<<j)*num1*2;
                }
            }
            printf("%lld
    ", ans);
        }
        return 0;
    }
    
    
    
  • 相关阅读:
    OC中nil、Nil、NULL、NSNull的区别
    SOJ 1050. Numbers & Letters
    SOJ 1009. Mersenne Composite N
    SOJ 1006. Team Rankings
    SOJ 1036. Crypto Columns
    SOJ 1151. 魔板
    SOJ 1007. To and Fro
    SOJ 1150.简单魔板
    SOJ 1051 Biker's Trip Odometer
    SOJ 1176 Two Ends
  • 原文地址:https://www.cnblogs.com/cniwoq/p/6770846.html
Copyright © 2020-2023  润新知