【问题标题】:Sum of bitwise OR of all possible subarrays of a given array给定数组的所有可能子数组的按位或总和
【发布时间】:2018-09-15 16:25:21
【问题描述】:

我想找到给定数组的所有可能子数组的按位或的总和。

这是我到现在为止所做的:

from operator import ior
from functools import reduce
n = int(input())
a = list(map(int, input().split()))
total = 0
for i in range(1,n+1):
    for j in range(n+1-i):
        total += reduce(ior, a[j:j+i])
print(total)

但是速度很慢。如何优化它?

【问题讨论】:

  • 兄弟,...不要作弊
  • 好吧......你得到了 5 个东西的按位或,现在你想要 5 个东西和一个 6 个东西的按位或......似乎你可以在这里重用一些东西而无需重新计算.. ..

标签: python python-3.x bitwise-or


【解决方案1】:

由于这个问题来自比赛,所以我一直没有回答。

代码:

#include <bits/stdc++.h>
using namespace std;
#define size 32
#define INT_SIZE 32
typedef long long int Int; 
typedef unsigned long long int Unt;
// Driver code
int main()
{
    Int n;
    cin>>n;
    Int arr[n];
    for(int i=0;i<n;i++)
        cin>>arr[i];
    int zeros[size];
    for(int i=0;i<size;i++)
        zeros[i]=1;
    unsigned long long int sum=0;
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<size;j++)
        {
            if(!(arr[i] & 1))
                zeros[j]++;
            else
            {
                sum+=(Unt)((Unt)zeros[j]*(Unt)(1<<j)*(Unt)(n-i));
                zeros[j]=1;
            }
            arr[i]>>=1;
        }
    }
    cout<<sum;
    return 0;
}

逻辑:

注意*:这是我的思考过程,可能不太容易理解。如果我不能让你理解,请道歉。

举个例子: 5(数组大小) 1 2 3 4 5(数组)

对于, 1 = 1.0

1,2 = 1.0 & 2.1

1,2,3 = 1.0 & 2.1 [3.0 & 3.1 不会有用,因为它们已经被 1 & 2 占用]

1,2,3,4 = 1.0 & 2.1 & 4.2

1,2,3,4,5 = 1.0 & 2.1 & 4.2 很有用。

在上面的解释中,X.Y 表示数字 X 中的第 Y 位用于 OR 操作。

为了,

2 = 2.1

2,3 = 2.1 & 3.0 [因为 1.0 将不可用]

{继续..}

因此,如果您仔细观察,尽管 3.0 可用,但 1 存在时它并没有被使用。

如果需要使用位,则前面的数字的相同位应为0。[记住这一点,我们稍后会使用它]

我们将创建 1 个名为 zeros 的数组,它分别给出每个位置上先前数字的最后一组的计数[这句话可能会让您感到困惑,尝试阅读更多内容,您可能会清楚]。

对于给定的数组,

在 1:0 0 0

在 2: 1 1 0 {1 的二进制是 001}

在 3: 2 0 1 {2 的二进制是 010}

在 4:3 0 0 {3 的二进制是 011}

在 5:0 1 1 {4 的二进制是 100}

结束:0 2 0 {5 的二进制是 101}

我们上面所做的是,如果位被设置位,我们将其设为 0,否则我们添加计数,以便我们可以分别了解有多少数字没有设置位位置,意思是,在 3、2 之前数字在位置 2^2 处没有设置位,1 个数字在 2^0 处没有设置位。

现在,我们只需要根据它们的设置位相乘即可。

如果设置位,那么我们将添加 (zeros[i]+1)(2^i)(n-i)。

【讨论】:

    【解决方案2】:

    让我们首先找到以位置 i 结尾的子数组的按位或的总和。设1到i的所有数组元素的OR为or,第i个元素为a[i]a[中未设置的位i] 中的设置来自一些以前的元素, 让我们在这里举个例子,
    1 2 2
    在位置 3,或 = 3,a[i] = 2,或^a[i] = 1 这意味着 1 来自某个先​​前的元素,如果我们删除 1 或某个以 i 结尾的子数组的 OR 将被减少。位 0 开启的最后一个位置是 1。 所以答案是,

    ans = or*i

    对于从 0 到 m 的所有位,
    ans -= (i - lastposition[bit])*(1 //lastposition[] 给出 bit 为 on 的最后一个索引。
    为什么是最后一个位置?因为该位打开的 lastposition[] 之前的索引不会产生影响,因为由于 lastposition[] 存在该位,OR 将保持相同。

    将1

    #include<bits/stdc++.h>
    #define ll long long
    #define pb push_back
    #define rep(i,a,b) for(int i = a; i <= b; i++)
    using namespace std;
    ll r, a, sum, pos[30];
    int main()
    {
       int n;
       cin >> n;
       rep(i,1,n)
      {
          cin >> a;
          r |= a;
          ll ex = r^a;
          ll ans = i*r;
          rep(bit,0,30)
            if(ex & (1 << bit))
                ans -= ((ll)(i - pos[bit])* ((ll)1 << bit));
         sum += ans;
         rep(bit,0,30)
            if(a & (1 << bit))
                pos[bit] = i;
    }
       cout << sum << '\n';
    }
    

    【讨论】:

      猜你喜欢
      • 2021-10-30
      • 2013-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-25
      • 1970-01-01
      • 1970-01-01
      • 2013-02-03
      相关资源
      最近更新 更多