1. 程式人生 > >CF1066EBinary Numbers AND Sum(字首和,二進位制)

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\n",&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; }