做法:
- 我们很容易推出,对于每一个位置到终点,先判断起始位置是1or0,是1初始化为1,是0初始化为0
- 从当前位置往后相邻两项如果不一样,那么+1,如果一样+2
- 举个例子:
- 1 0 1
- 1位置: 1 1+1 1+1+1
- 2位置: 2 2+1
- 3位置: 1
- ans = 1+2+3+2+3+1 = 12
- 然后多写几组数据,我们发现后一项是前一项删去第一项,然后每一项删除2或不变得来的。
- 这样的话我们维护一个前缀和的最后一项即可
AC代码:
#include<bits/stdc++.h>
#define IO ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define pb(x) push_back(x)
#define sz(x) (int)(x).size()
#define sc(x) scanf("%d",&x)
#define abs(x) ((x)<0 ? -(x) : x)
#define all(x) x.begin(),x.end()
#define mk(x,y) make_pair(x,y)
#define fin freopen("in.txt","r",stdin)
#define fout freopen("out.txt","w",stdout)
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int mod = 1e9+7;
const double PI = 4*atan(1.0);
const int maxm = 5e6+5;
const int maxn = 1e5+5;
const int INF = 0x3f3f3f3f;
const ll LINF = 1ll<<62;
ll a[maxn],dp[maxn];
char s[maxn];
int main()
{
// fin;
// IO;
int t;
sc(t);
while(t--)
{
memset(dp,0,sizeof(dp));
scanf("%s",s+1);
int len = strlen(s+1);
if(s[1] == '1') a[1] = 1;
else a[1] = 2;
for(int i=2;i<=len;i++)
{
if(s[i] == s[i-1]) a[i] = a[i-1]+2;
else a[i] = a[i-1]+1;
}
for(int i=1;i<=len;i++) dp[i] = dp[i-1]+a[i];
ll res = dp[len];
for(int i=2;i<=len;i++)
{
if(s[i-1] == '1') dp[len] = dp[len]-1;
if(s[i-1] == '0') dp[len] = dp[len]-2;
if(s[i-1] == '1' && s[i] == '0') dp[len] = dp[len];
else dp[len] = dp[len]-2*(len-i+1);
res+=dp[len];
}
printf("%lld\n",res);
}
return 0;
}