题目链接
题目大意
给你一个二进制01串,问你这个串有多少个好子串,设子串的起始和终止下标为 l 和 r ,那么好子串的定义为二进制子串换为十进制的数是等于(r-l+1)的
解题思路
因为这个串最长2e5,所以枚举的长度不超过18,但是因为有前导零的存在,我们不能只枚举长度为18的区间
我们用一个res来记录一下每个1前面有多少个前导零,如果当前的二进制数是小于等于res+r-l+1&&大于r-l+1的时候,就肯定存在一个好子串,也就是当前二进制数是大于不带前导零的长度的,但是长度可以用res个前导零补,所以最大的长度小于res+r-l+1的
比赛的时候想到了枚举长度肯定是很小的,但是不知道怎么处理前导零,然后就… … …
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int N=2e5+5;
char s[N];
int e[N];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%s",s+1);
int len=strlen(s+1);
for(int i=1;i<=len;i++)
e[i]=s[i]-'0';
int ans=0,res=0;
for(int i=1;i<=len;i++)
{
if(e[i]==0)
res++;
else
{
int xx=0;
for(int j=i,k=1;j<=len&&k<=19;j++,k++)
{
xx=xx*2+e[j];
if(xx<=res+(j-i+1)&&xx>=(j-i+1))
ans++;
}
res=0;
}
}
printf("%d\n",ans);
}
return 0;
}