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 <iostream> #include <math.h> #include <cstring> using namespace std; typedef long long int ll; const int SIZE = 100010; const int MOD = 1e9 + 7; int input[SIZE]; ll AND[SIZE]; ll OR[SIZE]; int sum[SIZE]; void fun(int left, int right, ll &result) { if (left == right) { result = (result + (((ll)input[left] * (ll)input[right]) % MOD)) % MOD; return; } int mid = (left+right+1) >> 1; ll pos = mid; AND[pos] = OR[pos] = input[mid]; sum[pos] = 1; for (int i = mid+1; i <= right; i++) { int newAnd = AND[pos] & input[i]; int newOr = OR[pos] | input[i]; if ((newAnd != AND[pos]) || (newOr != OR[pos])) { pos++; AND[pos] = newAnd; OR[pos] = newOr; sum[pos] = 1; } else { sum[pos]++; } } ll leftAnd = input[mid-1]; ll leftOr = input[mid-1]; for (int i = mid - 1; i >= left; i--) { leftAnd &= input[i]; leftOr |= input[i]; for (int j = mid; j <= pos; j++) { result = (result + ((((leftAnd & AND[j]) * (leftOr | OR[j])) % MOD) * sum[j]) % MOD) % MOD; } } fun(left, mid-1, result); fun(mid, right, result); } int main(int argc, const char * argv[]) { int n; cin >> n; for (int i = 0; i < n; i++) { cin >> input[i]; } ll result = 0; fun(0, n-1, result); cout << result << endl; return 0; }