由于这个问题来自竞争,我到现在还没有回答。
代码:
#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 很有用。
在上面的解释中,XY 表示数字 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 个数字没有t 在位置 2^2 设置了位,1 个数字没有在 2^0 设置位。
现在,我们只需要根据它们的设置位相乘。
如果它被设置位,那么我们将添加 (zeros[i]+1) (2^i) (ni)。