#include<stdio.h> #include <unordered_map> #include <algorithm> #include <list> #include <string.h> #include <stdlib.h> using namespace std; #define LL long long const int maxn=3e5+10; LL a[maxn]; LL odd[maxn]; LL even[maxn]; LL sum[maxn]; int main() { #ifdef shuaishuai freopen("in.txt","r",stdin); #endif // shuaishuai int n; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%lld",a+i); a[i]=__builtin_popcountll(a[i]); sum[i]=a[i]+sum[i-1]; } LL ans=0; even[0]=1; for(int i=1;i<=n;i++) { LL mx=a[i]; for(int j=i-1;j>=max(i-61,1);j--) { mx=max(mx,a[j]); LL s=sum[i]-sum[j-1]; if(s>=mx*2&&s&1^1) ans++;//如果区间成立则 mx需要<=sum/2且sum是偶数,反证法可证 } if(i>62) ans+=sum[i]&1? odd[i-63]:even[i-63]; //1e18以内的数最多62个1 所以对于极端情况 a1=a2=...a62=1 a63=62 只需将j遍历到2,j=1时aj有1的贡献,但是可推广开来计算.
//推广一下,对于 [i-61,i] 此时以a[i]结尾的合法序列除了ans统计的之外,还有根据sum[i]的奇偶不同而不同起点的序列,even[0]=1保证不漏掉a[1]...a[i]的序列的贡献 odd[i]+=odd[i-1]+(sum[i]&1); even[i]+=even[i-1]+(sum[i]&1^1); } for(int i=1;i<=n;i++) printf("%lld ",sum[i]);printf("\n"); for(int i=1;i<=n;i++) printf("%lld ",odd[i]);puts(""); for(int i=1;i<=n;i++) printf("%lld ",even[i]);puts(""); printf("%lld\n",ans); return 0; }
CodeForces-1030E 二进制位 dp
猜你喜欢
转载自www.cnblogs.com/polya/p/9711021.html
今日推荐
周排行