# Turn Off The Light

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Problem Description

There are n lights aligned in a row. These lights are numbered 1 to n from left to right. Initially some of the lights are turned on. Chiaki would like to turn off all the lights.
Chiaki starts from the p-th light. Each time she can go left or right (i.e. if Chiaki is at x, then she can go to x−1 or x+1) and then press the switch of the light in that position (i.e. if the light is turned on before, it will be turned off and vise versa).
For each p=1,2,…,n, Chiaki would like to know the minimum steps needed to turn off all the lights.

Input

There are multiple test cases. The first line of input is an integer T indicates the number of test cases. For each test case:
The first line contains an integer n (2≤n≤106) -- the number of lights.
The second line contains a binary string s where si=1 means the i-th light is turned on and si=0 means i-th light is turned off.
It is guaranteed that the sum of all n does not exceed 107.

Output

For each test cases, output (∑i=1|s|i×zi)mod(109+7), where zi is the number of step needed when Chikai starts at the i-th light.

Sample Input

 

3

3

000

3

111

8

01010101

Sample Output

 

0

26

432

Source

2018 Multi-University Training Contest 1

（刚开始补题的时候顺着比赛的时候的思路写，果然是错的。。最后参考了dls的讲题和代码，终于勉强弄懂了这题。）

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define N 105
#define INF 1e9
#define MOD 1000000007
using namespace std;
int z1[N],z2[N],n,sum[N],sum1[N],num[N],num1[N],T;
char s[N],g[N];
void work(char *s,int *z){
for(int i=1;i<=n;i++) z[i]=INF;
int lst=-1,fir=n+1;
for(int i=1;i<=n;i++)
if(s[i]==1){
lst=i;if(fir==n+1) fir=i;
}
if(lst==-1) {
for(int i=1;i<=n;i++) z[i]=0;
return ;
}
for(int i=1;i<=n;i++){
sum[i]=sum[i-1]^s[i]^1;
sum1[i]=sum1[i-1]^s[i];
num[i]=num[i-1]+sum[i];
num1[i]=num1[i-1]+sum1[i];
}
for(int i=1;i<=lst;i++){
int now=i,ans=0,now1;
if(i<=fir){
if(i==lst) {z[i]=3;continue;}
ans=lst-now;
if(sum[now-1]) ans+=2*(num[lst-1]-num[now-1]);
else ans+=2*(lst-now-num[lst-1]+num[now-1]);
if(sum[lst-1]^sum[now-1]^1) ans--;
z[i]=ans;
}else{
ans=lst-fir+now-fir;
now1=now;now=fir;
if(sum1[now-1])ans+=2*(num1[now1-1]-num1[now-1]);
else ans+=2*(now1-now-(num1[now1-1]-num1[now-1]));
if(sum1[now-1]^sum1[now1-1]^sum[now1-1]) ans+=2*(num[lst-1]-num[now1-1]);
else ans+=2*(lst-now1-(num[lst-1]-num[now1-1]));
if(sum[lst-1]^sum[now1-1]^sum1[now1-1]^sum1[fir-1]^1)ans--;
z[i]=ans;
}
}
}
int main(){
freopen("1.in","r",stdin);
scanf("%d",&T);
while(T--){
scanf("%d",&n);
scanf("%s",s+1);
for(int i=1;i<=n;i++) s[i]-='0';
for(int i=1;i<=n;i++) g[i]=s[n-i+1];
work(g,z2);
work(s,z1);
ll ans=0;
for(int i=1;i<=n;i++){
int x=min(z1[i],z2[n-i+1]);
ans=(ans+(ll)x*i%MOD)%MOD;
}
printf("%lld\n",ans);
}
}

05-19 429
11-05 1万+