CF1066EBinary Numbers AND Sum(前綴和,二進制)
阿新 • • 發佈:2018-10-18
復雜度 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(前綴和,二進制)