1. 程式人生 > >CF1066EBinary Numbers AND Sum(前綴和,二進制)

CF1066EBinary Numbers AND Sum(前綴和,二進制)

復雜度 tom += ans out tchar 第一個 stream color

題目大意

現在,給你兩個位數為 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; }

CF1066EBinary Numbers AND Sum(前綴和,二進制)