バイナリ文字列sを取得します(各文字が0または1の場合、文字列はバイナリであることを思い出してください)。
f(t)を整数tの10進数表現とし、バイナリ形式で記述します(先行ゼロが含まれる場合があります)。たとえば、f(011)= 3、f(00101)= 5、f(00001)= 1、(10)= 2、f(000)= 0およびf(000100)= 4。
r-l + 1 = f(sl ... sr)の場合、サブストリングsl、sl + 1、...、srが適切です。
たとえば、文字列s = 1011には5つの部分文字列があります:s1 ... s1 = 1、s3 ... s3 = 1、s4 ... s4 = 1、s1 ... s2 = 10、s2 ... s4 = 011。
あなたの仕事は、文字列s内の適切な部分文字列の数を数えることです。
解決策:
値と長さが等しい部分文字列の数を求めます。
この方法では、先行する0の数をリアルタイムでカウントし、各数値を開始点として使用して、リアルタイムでバイナリ文字列を生成します。長さの比率が小さく、先行する0の数が2つの差よりも大きい場合は、合法です。
#include <bits / stdc ++。h> using namespace std; typedef long long ll; const int maxn = 2e5 + 100 ; 文字列s; int main(){ int T; scanf(" %d "、&T); while(T-- ){ cin >> s; int ans = 0 ; int pre = 0 ; for(int i = 0 ; i <s.length(); i ++){ if(s [i] == ' 0 ' ) ++より 前; else { int r = i; int cnt = 1 ; for(int j = 0 ; j < 18 ; j ++ ){ if(cnt <= pre +(r-i + 1 )) ans ++ ; if(r == s.length()- 1 ) ブレーク ; cnt = cnt * 2 +(s [++ r]- ' 0 ' ); } // 前方拡張。長さが十分でない場合は、先頭の0 pre = 0 ; } } printf(" %d \ n " 、ans)を使用; } }