基准时间限制:1 秒 空间限制:131072 KB 分值: 40
难度:4级算法题
lyk拥有一个区间。
它规定一个区间的价值为这个区间中所有数and起来的值与这个区间所有数or起来的值的乘积。
例如3个数2,3,6。它们and起来的值为2,or起来的值为7,这个区间对答案的贡献为2*7=14。
现在lyk有一个n个数的序列,它想知道所有n*(n+1)/2个区间的贡献的和对1000000007取模后的结果是多少。
例如当这个序列为{3,4,5}时,那么区间[1,1],[1,2],[1,3],[2,2],[2,3],[3,3]的贡献分别为9,0,0,16,20,25。
Input
第一行一个数n(1<=n<=100000)。 接下来一行n个数ai,表示这n个数(0<=ai<=10^9)。
Output
一行表示答案。
Input示例
3 3 4 5
Output示例
70
alpq654321
(题目提供者)
C++ 11的运行时限为:1000 ms ,空间限制为:131072 KB
示例及语言说明请按这里
允许其他 AC 的用户查看此代码,分享代码才能查看别人的代码并有机会获得勋章
与运算规定该位为0,则包含该位的所有区间这一位对答案的贡献为0,所以我们每次找到该位为1的
一段连续区间,或运算就好算了,该区间内的数中只要有数的该位为1,则计入贡献就好了。
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<vector>
#include<string>
#include<math.h>
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<functional>
using namespace std;
#define ll long long
#define inf 1000000000
#define mod 1000000007
#define maxn 100005
#define lowbit(x) (x&-x)
#define eps 1e-9
int a[maxn],b[35];
ll ans;
int read()
{
char ch;
int n = 0;
ch = getchar();
while(ch >= '0' && ch <= '9'){
n = n * 10 + ch - '0';
ch = getchar();
}
return n;
}
int main(void)
{
int i,j,k,n;
n=read();
for(i=1;i<=n;i++)
a[i]=read();
for(i=0;i<31;i++)
{
int l=1,r,num=(1<<i);
while(1)
{
for(;l<=n;l++)
if(a[l]&num)
break;
if(l>n)
break;
for(r=l+1;r<=n;r++)
if(!(a[r]&num))
break;
r--;
for(j=0;j<31;j++)
b[j]=0;
for(j=l;j<=r;j++)
for(k=0;k<31;k++)
{
if(a[j]&(1<<k))
b[k]=j;
if(b[k])
{
ans+=(ll)num*(b[k]-l+1)%mod*((1<<k)%mod);
ans%=mod;
}
if(ans<0)
ans+=mod;
}
l=r+1;
}
}
printf("%lld\n",ans);
return 0;
}