.
.
解法:注意每一个1能够往后移动的次数就是他后面0的位数,假设后面有zero个0,ques个?,那么这个位置可以往后移动(zero + (zero+1)+…+(zero+ques)),这个就可以用一个等差数列来记录,然后还要乘以这个数前面 2^(问号数),加起来就是答案了
.
.
#include <cstdio>
#include <cstring>
const long long m = 1000000007;
char a[600010];
int preq[600010], b[600010];
long long ques = 0, zeros = 0, tmp = 0, ans = 0;
int main() {
scanf("%s", a);
int n = strlen(a);
if (a[0] == '?') preq[0] = 1;
else preq[0] = 0;
for (int i = 1; i < n; i++) {
if (a[i] == '?') preq[i] = preq[i - 1] + 1;
else preq[i] = preq[i - 1];
}
b[0] = 1;
for (int i = 1; i <= n; i++) b[i] = b[i - 1] * 2 % m;
for (int i = n - 1; i >= 1; i--) {
if (a[i] == '0') {
zeros++;
} else if (a[i] == '1') {
if (ques == 0) {
ans = (ans + zeros) % m;
} else {
tmp = ((ques * b[ques - 1] % m) + (zeros * b[ques] % m)) % m * (b[preq[i - 1]]) % m;
ans = (ans + tmp) % m;
}
} else {
if (ques == 0) {
ans = (ans + zeros) % m;
} else {
tmp = ((ques * b[ques - 1] % m) + (zeros * b[ques] % m)) % m * (b[preq[i - 1]]) % m;
ans = (ans + tmp) % m;
}
ques++;
}
}
if (a[0] != '0') {
if (ques == 0) {
ans = (ans + zeros) % m;
} else {
tmp = ((ques * b[ques - 1] % m) + (zeros * b[ques] % m)) % m;
ans = (ans + tmp) % m;
}
}
printf("%lld\n", ans);
}