Description

现在我们有一个由01组成的字符串。我们需要在上面做一些操作。每次我们都选一个“01”子串,把他替换成110。如果找不到“01”子串,那么操作结束。请输出总共进行了多少次操作,结果请mod 1e9+7。

 

Ps:“01”子串必须是相邻的0和1,字符串中只包含0和1。

 

 

Input

首先一个T,代表接下来有T行。

接下来的T行,每行一个字符串str

(1<= T <= 200, 所有字符串长度和 len <= 2e7)

Output

 对于每个字符串,输出相应操作数。

 

Sample Input

2
01
001

Sample Output

1
3

HINT

 

对于第二个字符串:

 

001 -> 0110 -> 11010 -> 111100

C++版本一

题解:

多模拟几个字符串的操作可以发现最后都会变成类似11111110000000的形式,即所有的1转移到左边,0转移到右边,且0在转移到右边的过程中个数不变。

对于01需要1(2^1-1)次,001需要3(2^2-1)次, 0001需要7(2^3-1)次,即对于每个1,如果它前面有N个0,则这N个0跳过这个1需要(2^N-1)次。

我们就可以直接遍历字符串,然后统计0的个数cnt,碰到1则将(2^cnt-1)加到答案中。

这里计算2^cnt-1不能用快速幂,直接用前面的*2即可,否则可能会超时。

#include<cstdio>
#define LL long long
LL mod = 1e9+7;
const int maxn = 1e6+10;
 
char str[maxn];
 
int main() {
    //freopen("data1.in","r",stdin);
    //freopen("out.txt","w",stdout);
    int t;
    scanf("%d",&t);
    while(t--) {
        scanf("%s",str);
        LL ans = 0,ba = 1;
        for(int i = 0;str[i];i++) {
            if(str[i] == '0') ba = ba*2%mod;
            else ans = (ans+ba-1)%mod;
        }
        printf("%lld\n",ans);
    }
}

 C++版本二

题解:

快速幂

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <string.h>
#include <cmath>
#include <queue>
using namespace std;
typedef long long ll;
const int N=2e7+100;
const int M=1e9+7;
int t,n,m;
char a[N];
int p[N];
void pow2(){
    ll tmp=1;
    p[0]=tmp;
    for(int i=1;i<=N;i++){
        tmp*=2;
        tmp%=M;
        p[i]=tmp;
    }
}
int main()
{
    scanf("%d",&n);
    pow2();
    while(n--){
        scanf("%s",a);
        int len=strlen(a);
        int cnt=0;
        ll ans=0;
        for(int i=0;i<len;i++){
            if(a[i]=='0')
                cnt++;
            else{
                ans+=(p[cnt]-1);
                ans%=M;
            }
        }
        cout << ans << endl;
    }
    //cout << "Hello world!" << endl;
    return 0;
}