51NOD-1674 区间的价值 V2

原题链接

基准时间限制: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
求出每一位的连续区间l, r,满足在这个区间上的数的该位都是1,在求出l, r区间上所有子区间的or值之和,再相乘

#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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值