Codeforces E. Binary Numbers AND Sum 规律

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xiang_6/article/details/83819779

CF: *1700

题意:

给定两个很大的二进制数a,b,长度最大2e5,答案每次加上 a&b (位运算),然后b右移一位,直到为0;

问最后答案是多少

思路:

先把两个串都翻转,下标从1开始,便于描述规律:

b这个数每次右移一位,所以现在可以看作这个串往左移动,所以b中的第i位如果为1 ,那他跟a串中的前i个数会进行i次&运算,

所以可以从这个角度来考虑b中的每个1做出的贡献,

对于样例1(从左往右看):b中第一个1跟a做运算得到1010,第二个1跟a运算得到010,第三个1跟a运算得到0,所以和是12

对于样例2(从左往右看):如果a长度<b长度,a高位补零,此时a=01001,b=10101;所以b中1的贡献(二进制表示):1001 + 001 + 1 = 11;

#include<bits/stdc++.h>

using namespace std;

#define out fflush(stdout);
#define fast ios::sync_with_stdio(0),cin.tie(0);

#define FI first
#define SE second

typedef long long ll;
typedef pair<ll,ll> P;

const int maxn = 2e5 + 7;
const int INF = 0x3f3f3f3f;
const ll mod = 998244353;


int n, m;
char s[maxn], t[maxn];
ll ans = 0;

void swap_() {
    int l = 1, r = n;
    while(l < r) {
        swap(s[l], s[r]);
        l++; r--;
    }
    l = 1, r = m;
    while(l < r) {
        swap(t[l], t[r]);
        l++; r--;
    }
}

ll pow_(ll a, int n) {
    ll res = 1;
    while(n) {
        if(n&1) res = (res * a) % mod;
        a = (a * a) % mod;
        n >>= 1;
    }
    return res;
}

int main() {
    scanf("%d%d", &n, &m);
    scanf("%s%s", s+1, t+1);
    swap_();

    ll cur = 0;
    for(int i = 1; i <= m; ++i) {
        if(i <= n && s[i] == '1') cur = (cur + pow_(2, i-1)) % mod;
        if(t[i] == '1') {
            ans = (ans + cur) % mod;
        }
    }
    printf("%lld\n", ans);

    return 0;
}

猜你喜欢

转载自blog.csdn.net/xiang_6/article/details/83819779