题目链接:http://codeforces.com/problemset/problem/608/B
题目意思:给出两个字符串 a 和 b,然后在b中找出跟 a 一样长度的连续子串,每一位进行求相减的绝对值然后相加(这个讲得有点绕),直接举个例子就很容易理解了。
假设a = 01,b = 00111,
符合条件的b的子串有:00, 01, 11, 11
然后: |01-00| = |0-0| + |1-0| = 1,
|01-01| = |0-0| + |1-1| = 0,
|01-11| = |0-1| + |1-1| = 1,
|01-11| = |0-1| + |1-1| = 1,
再求和:1 + 0 + 1 + 1 = 3
这个挺考观察能力的= =
枚举 a 的每一位,然后找出 b 中哪些子串需要跟a的这一位进行运算的。
假设 a = 010,b = 00111,la:a的字符串长度, lb:b的字符串长度
第 i 位 需要 b 的 哪几位进行运算
1 1, 2, 3
2 2, 3, 4
3 3, 4, 5
然后有个这样的关系:对于字符串a中第 i 位,需要b中 i ~ lb-(la-i) 的这些数进行运算。
可以发现,如果 a 中第 i 位的数为1, 那么b中 i ~ lb-(la-i) 的这些数为 0 跟它相减才等于1,否则为0; a 为 0 的话亦然。。。。最后就是注意用 long long 啦,10^18很大呢~
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 using namespace std; 6 7 const int maxn = 200000 + 5; 8 char a[maxn], b[maxn]; 9 int c0[maxn], c1[maxn]; 10 11 long long res; 12 13 int main() 14 { 15 #ifndef ONLINE_JUDGE 16 freopen("in.txt", "r", stdin); 17 #endif // ONLINE_JUDGE 18 19 while (scanf("%s%s", a+1, b+1) != EOF) { 20 int la = strlen(a+1); 21 int lb = strlen(b+1); 22 23 memset(c0, 0, sizeof(c0)); 24 memset(c1, 0, sizeof(c1)); 25 26 for (int i = 1; i <= lb; i++) { 27 c1[i] = c1[i-1]; 28 c0[i] = c0[i-1]; 29 30 if (b[i] == '0') { 31 c0[i]++; 32 } 33 else { 34 c1[i]++; 35 } 36 } 37 38 res = 0; 39 for (int i = 1; i <= la; i++) { 40 if (a[i] == '0') { // 统计跟它比对的1的个数 41 res += (c1[lb-(la-i)]-c1[i-1]); 42 } 43 else { 44 res += (c0[lb-(la-i)]-c0[i-1]); 45 } 46 } 47 printf("%lld ", res); 48 } 49 return 0; 50 }