基准时间限制: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
#include <bits/stdc++.h>
#define maxn 100005
#define MOD 1000000007
using namespace std;
typedef long long ll;
int vis[35];
int num[maxn];
int get_int(){
char ch;
int n = 0;
ch = getchar();
while(ch >= '0' && ch <= '9'){
n = n * 10 + ch - '0';
ch = getchar();
}
return n;
}
int main(){
// freopen("in.txt", "r", stdin);
ll ans = 0;
int n;
scanf("%d", &n);
getchar();
for(int i = 1; i <= n; i++)
num[i] = get_int();
for(int i = 0; i < 31; i++){
int l = 1, r, d = 1 << i;
while(1){
for(; l <= n; l++){
if(num[l] & d){
break;
}
}
if(l > n)
break;
for(r = l; r <= n; r++){
if(!(num[r] & d)){
break;
}
}
r--;
memset(vis, 0, sizeof(vis));
for(int h = l; h <= r; h++){
for(int j = 0; j < 31; j++){
if(num[h]&(1<<j)){
vis[j] = h;
}
if(vis[j]){
ans += (ll)d * (vis[j] - l + 1) % MOD * ((1<<j) % MOD);
ans %= MOD;
}
}
}
l = r + 1;
}
}
printf("%I64d\n", ans);
return 0;
}