codeforces 336 Div.2 B. Hamming Distance Sum

题目链接: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\n", res);
48     }
49     return 0;
50 }

  

posted @ 2016-01-01 23:55  windysai  阅读(200)  评论(0编辑  收藏  举报