【JZOJ3518】進化序列【模擬】
阿新 • • 發佈:2018-12-15
題目大意:
題目連結: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;
}