Codeforces 1017B The Bits(前缀和)

题目链接:The Bits

题意

给定由 n n 01 位组成的二进制数 a a b,问对 a a 的所有 01 位有多少种交换不同位的方式,使得 a or b a   o r   b (按位或)的值发生改变。

输入

第一行为一个整数 n (2n105) n   ( 2 ≤ n ≤ 10 5 ) ,第 2 2 行为 n 01 01 字符,表示 a a 的所有二进制位,第 3 行为 n n 01 字符,表示 b b 的二进制位。

输出

输出方案数。

样例

输入
5
01011
11001
输出
4
提示
a 中可以交换的 01 01 位为: (1,4),(2,3),(3,4),(3,5) ( 1 , 4 ) , ( 2 , 3 ) , ( 3 , 4 ) , ( 3 , 5 )

输入
6
011000
010011
输出
6
提示
a a 中可以交换的 01 位为: (1,2),(1,3),(2,4),(3,4),(3,5),(3,6) ( 1 , 2 ) , ( 1 , 3 ) , ( 2 , 4 ) , ( 3 , 4 ) , ( 3 , 5 ) , ( 3 , 6 )
题解

枚举所有 a a b 01 01 位的对应情况:

  1. a a 0 的位对应的是 b b 0 的位,与另一个 a a 1 的位交换,当前位置上的或值将会从 0 0 变为 1
  2. a a 0 的位对应的是 b b 1 的位,与另一个 a a 1 b b 0 的位交换,那么被交换的位置上的或值将会从 1 1 变为 0
  3. a a 1 的位对应的是 b b 0 的位,与另一 a a 0 的位交换,当前位置上的或值将会从 1 1 变为 0
  4. a a 1 的位对应的是 b b 1 的位,与另一个 a a 0 b b 0 的位交换,被交换的位置上的或值将会从 0 0 变为 1

因此按照所有对应位置上 ab a b 01 01 状态求前缀和或者后缀和,最后 O(n) O ( n ) 扫一遍就能得到答案。

过题代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cstring>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <algorithm>
#include <functional>
#include <iomanip>
using namespace std;

#define LL long long
const int maxn = 100000 + 100;
int n;
int sum[maxn][4];
char a[maxn], b[maxn];

int id(int i) {
    return (a[i] - '0') * 2 +  b[i] - '0';
}

int main() {
    #ifdef LOCAL
    freopen("test.txt", "r", stdin);
//    freopen("test1.out", "w", stdout);
    #endif // LOCAL
    ios::sync_with_stdio(false);

    while(scanf("%d", &n) != EOF) {
        memset(sum, 0, sizeof(sum));
        scanf("%s%s", a + 1, b + 1);
        for(int i = n; i > 0; --i) {
            for(int j = 0; j < 4; ++j) {
                sum[i][j] = sum[i + 1][j];
            }
            ++sum[i][id(i)];
        }
        LL ans = 0;
        for(int i = 1; i < n; ++i) {
            switch(id(i)) {
                case 0: ans += sum[i + 1][2] + sum[i + 1][3]; break;
                case 1: ans += sum[i + 1][2]; break;
                case 2: ans += sum[i + 1][0] + sum[i + 1][1]; break;
                case 3: ans += sum[i + 1][0]; break;
                default: break;
            }
        }
        printf("%I64d\n", ans);
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值