标签:mes cal names ott 预处理 code fine gis ali
现在,给你两个位数为 n 和 m 的两个二进制数a,b,现在,我们要进行如下操作:
现在,请你算出最终的答案,并输出,答案对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(前缀和,二进制)
标签:mes cal names ott 预处理 code fine gis ali
原文地址:https://www.cnblogs.com/ztz11/p/9807576.html