Problem Statement | |||||||||||||
This problem deals with binary strings: strings in which each character is either '0' or '1'. The characters are interpreted as zeros and ones. Assume that we have a binary string of length N. Imagine the string as a horizontal lever of length N-1. The weight of the lever is negligible. On the lever, the points with integer coordinates are numbered from 0 (one end of the lever) to N-1 (the other end). Our string represents the distribution of weights on this lever. For each i, if character i of our string is '0', the corresponding point is empty, and if the character is '1', there is a unit weight at that point. Suppose that we place a fulcrum under the point number i. We say that element i of the string is a balance point if the lever is balanced on the fulcrum: the moments of force on either side cancel each other out. A string is called a balanced string if it has at least one balance point. Note that the balance point must be one of the marked points (see examples below). A formal definition follows. For each valid index i we can compute the torque at i as follows:
For example, the string "10100001" is a balanced string. Its balance point is the (0-based) index i=3. If we put the fulcrum under the lever at this position, we see "101" to the left and "0001" to the right. On the left side we get A = 1*3 + 0*2 + 1*1 = 4, and on the right side we get B = 0*1 + 0*2 + 0*3 + 1*4 = 4, hence A-B is exactly zero. The string "0001" is also a balanced string, as its last character is a balance point. The string "11" is not a balanced string, as neither of its two characters is a balance point. You are given a string s that is a binary string. Return the number of nonempty substrings of s that are balanced. Substrings that consist of the same characters but occur elsewhere in s are considered different substrings. If they are balanced, each of them should be counted separately. For example, the string "00000" contains four distinct occurrences of the substring "00". | |||||||||||||
Definition | |||||||||||||
| |||||||||||||
Limits | |||||||||||||
| |||||||||||||
Constraints | |||||||||||||
- | s will have between 1 and 2,500 characters, inclusive. | ||||||||||||
- | Each character in s will be '0' or '1'. | ||||||||||||
Examples | |||||||||||||
0) | |||||||||||||
| |||||||||||||
1) | |||||||||||||
| |||||||||||||
2) | |||||||||||||
| |||||||||||||
3) | |||||||||||||
| |||||||||||||
4) | |||||||||||||
|
This problem statement is the exclusive and proprietary property of TopCoder, Inc. Any unauthorized use or reproduction of this information without the prior written consent of TopCoder, Inc. is strictly prohibited. (c)2003, TopCoder, Inc. All rights reserved.
法一:
预处理从a[i,j]表示以i为支点到j对天平的贡献,
枚举支点 O(n^3)
二分支点 O(n^2logn)
固定左端点,随右端点增大向右推支点 O(n^2)
法二:
根据力矩公式,向右推一个支点,左右力矩和差减小sum(区间内1的个数),取Mod sum即可.
注意全为0的情况
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<iostream>
#include<cmath>
#include<cctype>
#include<ctime>
#include<string>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Lson (x<<1)
#define Rson ((x<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define MAXN (2500+10)
long long mul(long long a,long long b){return (a*b)%F;}
long long add(long long a,long long b){return (a+b)%F;}
long long sub(long long a,long long b){return (a-b+(a-b)/F*F+F)%F;}
typedef long long ll;
class BalancedSubstrings
{
public:
ll a[MAXN][MAXN],b[MAXN][MAXN];
int sum[MAXN][MAXN];
bool is[MAXN][MAXN];
bool v[MAXN];
int countSubstrings(string s)
{
int n=s.length();
MEM(a) MEM(b) MEM(is)
MEM(v) MEM(sum)
Rep(i,n) v[i]=(s[i]=='1');
Rep(i,n)
Fork(j,i,n-1) sum[i][j]=sum[i][j-1]+(s[j]-'0');
Rep(i,n)
Fork(j,i+1,n-1) a[i][j]=a[i][j-1]+(j-i)*(s[j]-'0');
Rep(i,n)
RepD(j,i-1) a[i][j]=a[i][j+1]-(i-j)*(s[j]-'0');
int ans=0;
Rep(i,n)
{
Fork(j,i,n-1) {
if (i==j) {++ans;is[i][j]=1;continue;}
if (is[i][j-1]&&(!v[j])) {++ans;is[i][j]=1;continue;}
if (is[i+1][j]&&(!v[i])) {++ans;is[i][j]=1;continue;}
if (i<j-1&&is[i+1][j-1]&& (!(v[i]^v[j])) ) {++ans;is[i][j]=1;continue;}
int tot=sum[i][j];
if (a[i][j]%tot==0)
{
++ans;
is[i][j]=1;
continue;
}
}
}
return ans;
}
}S;
string s;
int main()
{
freopen("s.out","r",stdin);
// freopen(".out","w",stdout);
cin>>s;
cout<<S.countSubstrings(s)<<endl;
return 0;
}