题目大意:
题目链接:https://jzoj.net/senior/#main/show/3518
题目图片:
http://wx2.sinaimg.cn/mw690/0060lm7Tly1fy2vsa8tmfj30jd0boaab.jpg
http://wx2.sinaimg.cn/mw690/0060lm7Tly1fy2vsa8oz7j30j309t3yi.jpg
给出一个数列,求的个数。
思路:
很明显的,如果,那么。
那么就可以维护两个指针,表示,每次往后移一位,用表示从到中二进制下第位是的个数。将所表示的数和比较,如果还符合要求,那么就要加。因为,那么,,以此类推。
如果不符合要求,那么就将指针往后移。知道符合要求为止。
时间复杂度
代码:
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const int LG=31;
const int N=100100;
int n,m,i,j,a[N],num[LG+1];
ll ans;
bool check() //判断num大还是m大
{
int mm=0;
for (int i=LG;i>=1;i--)
mm+=((num[i]>0)*(1<<(i-1)));
return mm<m;
}
void write(ll x) //输出流,防止炸long long
{
if (x>9) write(x/10);
putchar(x%10+48);
}
int main()
{
freopen("evolve.in","r",stdin);
freopen("evolve.out","w",stdout);
scanf("%d%d",&n,&m);
for (i=1;i<=n;i++)
scanf("%d",&a[i]);
j=1;
i=0;
while (i<n)
{
i++;
for (int k=1;k<=LG;k++)
num[k]+=((a[i]&(1<<(k-1)))==(1<<(k-1)));
while (!check())
{
for (int k=1;k<=LG;k++)
num[k]-=((a[j]&(1<<(k-1)))==(1<<(k-1)));
j++;
}
ans+=(ll)max((i-j),0);
}
write(ans);
return 0;
}