CF1066EBinary Numbers AND Sum(前缀和,二进制)

Posted ztz11

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF1066EBinary Numbers AND Sum(前缀和,二进制)相关的知识,希望对你有一定的参考价值。

题目大意

现在,给你两个位数为 n 和 m 的两个二进制数a,b,现在,我们要进行如下操作:

  • 计算a&b
  • 答案累加上一个操作的值
  • bbb右移一位,最后一位直接舍弃

现在,请你算出最终的答案,并输出,答案对998244353取模

输入输出格式:

输入格式:

第一行,两个整数n,m,(1≤n,m≤2×105)

第一行,一个长度为n的二进制数a

第一行,一个长度为m的二进制数b

输出格式:

一行,一个数,表示答案

思路:

因为第一个二进制数不动,第二个在动,所以我们可以通过预处理第一个数来获得答案

因为是与,所以只有两个都是1时才会有答案的贡献

那么,比如说这个例子:

1001
11010

他就会有如下几种情况

01001
11010

1001
1101

1001
0110

1001
0011

1001
0001

我们会发现,第一位的1分别和上面的第一个1和最后一个1异或起来对答案有贡献

所以这个1对答案的贡献是8+1=9

我们把这个规律推广开来

对y中每一个1进行如上操作

即可得出答案

但是,我们会发现答案复杂度是O(n×m)的,过不了

所以我们要预处理

用前缀和跑一遍x即可

复杂度优化到O(m+n)

代码:

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define rii register int i
#define rij register int j
#define p 998244353
#define int long long
using namespace std;
int a,b;
int x[200005],y[200005],bs[200005],qzh[200005];
void ycl()
{
    bs[0]=1;
    for(rii=1;i<=200002;i++)
    {
        bs[i]=bs[i-1]*2;
        bs[i]%=p;
    }
}
signed main()
{
    scanf("%lld%lld
",&a,&b);
    for(rii=1;i<=a;i++)
    {
        x[i]=getchar()-0;
    }
    getchar();
    for(rii=1;i<=b;i++)
    {
        y[i]=getchar()-0;
    }
    ycl();
    for(rii=a;i>=1;i--)
    {
        qzh[a-i+1]=qzh[a-i];
        qzh[a-i+1]+=x[i]*bs[a-i];
        qzh[a-i+1]%=p;
    }
    if(b>a)
    {
        for(rii=a+1;i<=b;i++)
        {
            qzh[i]=qzh[i-1];
        }
    }
//  for(rii=1;i<=b;i++)
//  {
//      printf("%d ",qzh[i]);
//  }
    int ans=0;
    for(rii=1;i<=b;i++)
    {
        ans+=y[i]*qzh[b-i+1];
        ans%=p;
    }
    cout<<ans%p;
}

 

以上是关于CF1066EBinary Numbers AND Sum(前缀和,二进制)的主要内容,如果未能解决你的问题,请参考以下文章

Python 操作Redis

python爬虫入门----- 阿里巴巴供应商爬虫

Python词典设置默认值小技巧

《python学习手册(第4版)》pdf

Django settings.py 的media路径设置

Python中的赋值,浅拷贝和深拷贝的区别