cf1066E Binary Numbers AND Sum

本文解析了CodeForces竞赛中一道涉及大整数运算和位运算的难题,阐述了解题思路并提供了C++代码实现,通过计算两个大二进制数在一系列位运算后的结果模998244353。

题目:http://codeforces.com/contest/1066/problem/E

You are given two huge binary integer numbers aa and bb of lengths nn and mm respectively. You will repeat the following process: if b>0b>0, then add to the answer the value a & ba & b and divide bb by 22 rounding down (i.e. remove the last digit of bb), and repeat the process again, otherwise stop the process.

The value a & ba & b means bitwise AND of aa and bb. Your task is to calculate the answer modulo 998244353998244353.

Note that you should add the value a & ba & b to the answer in decimal notation, not in binary. So your task is to calculate the answer in decimal notation. For example, if a=10102 (1010)a=10102 (1010) and b=10002 (810)b=10002 (810), then the value a & ba & b will be equal to 88, not to 10001000.

Input

The first line of the input contains two integers nn and mm (1≤n,m≤2⋅1051≤n,m≤2⋅105) — the length of aa and the length of bb correspondingly.

The second line of the input contains one huge integer aa. It is guaranteed that this number consists of exactly nn zeroes and ones and the first digit is always 11.

The third line of the input contains one huge integer bb. It is guaranteed that this number consists of exactly mm zeroes and ones and the first digit is always 11.

Output

Print the answer to this problem in decimal notation modulo 998244353998244353.

Examples

input

Copy

4 4
1010
1101

output

Copy

12

input

Copy

4 5
1001
10101

output

Copy

11

给出两个大数a和b,要求计算(a&b) + (a & (b >> 1)) + (a & (b >> 2)) + ...

如果只是计算a&b那么我们只需要把a和b的二进制存下来扫一遍就行了,现在多了几项东西,其实道理是一样的,我们看比这一位高的有多少个1,就会在这一位有多少贡献,前缀和维护一下。

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
typedef long long ll;
const ll mod = 998244353;
int abit[N];
int bbit[N];
char s[N];
int main()
{
    int a, b;
    scanf("%d%d", &a, &b);
    memset(abit, 0, sizeof(abit));
    memset(bbit, 0, sizeof(bbit));
    scanf("%s", s);
    for (int i = 0; i < a; i++)
    {
        abit[a - i - 1] = s[i] - '0';
    }
    scanf("%s", s);
    for (int i = 0; i < b; i++)
    {
        bbit[b - i - 1] = s[i] - '0';
        if (i)
            bbit[b - i - 1] += bbit[b - i];
        //printf("%c %d\n", s[i], bbit[b - i - 1]);
    }
    ll power = 1;
    ll sum = 0;
    for (int i = 0; i <= max(a, b); i++)
    {
        if (abit[i])
        {
            sum += bbit[i] * power % mod;
            sum %= mod;
        }
        power = power * 2 % mod;
    }
    cout << sum << endl;
    return 0;
}

 

data segment ; 定义所有需要显示的字符串 menu db 'Menu:',0dh,0ah db '1. Input',0dh,0ah db '2. Exit',0dh,0ah db 'Please choose: $' prompt1 db 'First number: $' prompt2 db 'Second number: $' crlf db 0dh,0ah,'$' ; 回车换行 bin_msg db 'Binary : $' dec_msg db 'Decimal : $' hex_msg db 'Hexadecimal : $' error_choice db 'Invalid choice, please enter 1 or 2.$' error_num db 'Invalid number, please enter 0-9.$' data ends code segment assume cs:code, ds:data start: mov ax, data mov ds, ax ; 初始化数据段 menu_loop: ; 显示菜单 mov ah, 09h lea dx, menu int 21h ; 读取用户选择 mov ah, 01h int 21h push ax ; 保存用户选择 ; 处理输入后的回车换行 mov ah, 09h lea dx, crlf int 21h ; 判断用户选择(修改部分:解决跳转范围问题) pop ax cmp al, '1' jne check_exit ; 不相等则检查是否为2,避免短跳转范围不足 jmp input_numbers ; 用无条件跳转处理较远目标 check_exit: cmp al, '2' jne invalid_choice ; 不相等则为无效选择 jmp exit_program ; 用无条件跳转处理较远目标 invalid_choice: ; 无效选择处理 mov ah, 09h lea dx, error_choice int 21h mov ah, 09h lea dx, crlf int 21h jmp menu_loop ; 返回菜单 input_numbers: ; 输入第一个数字 mov ah, 09h lea dx, prompt1 int 21h mov ah, 01h int 21h cmp al, '0' jb invalid_number ; 小于'0',无效 cmp al, '9' ja invalid_number ; 大于'9',无效 sub al, 30h ; 转换为数值 mov bl, al ; 保存第一个数到bl ; 处理回车换行 mov ah, 09h lea dx, crlf int 21h ; 输入第二个数字 mov ah, 09h lea dx, prompt2 int 21h mov ah, 01h int 21h cmp al, '0' jb invalid_number cmp al, '9' ja invalid_number sub al, 30h ; 转换为数值 add al, bl ; 计算和,结果在al中 mov bh, al ; 保存结果到bh ; 处理回车换行 mov ah, 09h lea dx, crlf int 21h ; 显示十进制结果 mov ah, 09h lea dx, dec_msg int 21h call print_decimal mov ah, 09h lea dx, crlf int 21h ; 显示十六进制结果 mov ah, 09h lea dx, hex_msg int 21h call print_hex mov ah, 09h lea dx, crlf int 21h ; 显示二进制结果 mov ah, 09h lea dx, bin_msg int 21h call print_binary mov ah, 09h lea dx, crlf int 21h jmp menu_loop ; 返回菜单 invalid_number: ; 处理无效数字输入 mov ah, 09h lea dx, crlf int 21h lea dx, error_num int 21h mov ah, 09h lea dx, crlf int 21h jmp menu_loop ; 返回菜单 ; 子程序:打印十进制结果 print_decimal: push ax push bx push cx push dx mov al, bh mov ah, 0 ; 清除ah,准备除法 mov bl, 10 ; 除数为10 div bl ; al = 商(十位),ah = 余数(个位) mov bl, ah ; 保存个位数 ; 输出十位数 mov dl, al add dl, 30h ; 转换为ASCII mov ah, 02h int 21h ; 输出个位数 mov dl, bl add dl, 30h mov ah, 02h int 21h pop dx pop cx pop bx pop ax ret ; 子程序:打印十六进制结果 print_hex: push ax push bx push cx push dx mov al, bh mov cl, 4 shr al, cl ; 取高4位 cmp al, 0ah jb hex1 ; 小于10直接转换 add al, 7h ; 大于等于10,加7后再转换 hex1: add al, 30h mov dl, al mov ah, 02h int 21h mov al, bh and al, 0fh ; 取低4位 cmp al, 0ah jb hex2 add al, 7h hex2: add al, 30h mov dl, al mov ah, 02h int 21h pop dx pop cx pop bx pop ax ret ; 子程序:打印二进制结果(修正版) print_binary: push ax push bx push cx push dx mov bl, bh ; 将结果存入bl mov cx, 8 ; 循环8次(8位) bin_loop: mov dl, '0' ; 默认输出'0' shl bl, 1 ; 左移,最高位移到CF jnc print_bit ; 如果CF=0,跳转到输出 mov dl, '1' ; 如果CF=1,输出'1' print_bit: mov ah, 02h int 21h loop bin_loop ; 循环8次 pop dx pop cx pop bx pop ax ret exit_program: mov ah, 4ch int 21h ; 退出程序 code ends end start请尝试优化该段代码
最新发布
09-28
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值