51nod1674 区间的价值
题意:输入一个序列,区间的价值定义为这个区间的所有数&乘以所有数|,问所有区间的价值为多少?
题解:这里要知道,f1(1, j) = and(a[1], a[2]... a[j])随着j增大f(i, j)的1个数会减少或不变,所以最后f的值最多只有log(n)个
分治算答案.对于一个区间,左右分治,再计算跨越mid的区间的价值,右边的值最多有log(len)个那么可以分块计算答案,复杂度n*logn*logn
#include <bits/stdc++.h> #define maxn 101000 #define INF 0x3f3f3f3f typedef long long ll; using namespace std; const ll mod = 1e9+7; int aor[maxn], aand[maxn], num[maxn], a[maxn]; ll f(int l,int r){ if(l == r) return (ll)a[l]*a[l]; int mid = (l+r)>>1; ll ans = 0; ans = (ans+f(l, mid)+f(mid+1, r))%mod; int n = 1; num[n] = 1; aor[n] = aand[n] = a[mid+1]; for(int i=mid+2;i<=r;i++){ if(((aor[n]|a[i]) != aor[n])||((aand[n]&a[i]) != aand[n])){ n++; aor[n] = aor[n-1]|a[i]; aand[n] = aand[n-1]&a[i]; num[n] = 1; } else num[n]++; } int t1 = a[mid], t2 = a[mid]; for(int i=mid;i>=l;i--){ t1 &= a[i], t2 |= a[i]; for(int j=1;j<=n;j++) ans = (ans+(ll)(t1&aand[j])*num[j]%mod*(t2|aor[j])%mod)%mod; } return (ans+mod)%mod; } int main(){ int n; scanf("%d", &n); for(ll i=1;i<=n;i++) scanf("%d", &a[i]); printf("%lld\n", f(1, n)); return 0; }
posted on 2018-03-14 17:22 2855669158 阅读(168) 评论(0) 编辑 收藏 举报