Codeforces Round #515 (Div. 3) E(模拟+前缀和)

题意:a和b是两个01字符串,现要计算a&b+a&b>>1+a&b>>2+……(直到b=0)

思路: 因为a和b的长度不确定,所以给短的那个在前面补上0,因为b每一次往右移,所以可以计算b的每一位上的贡献,这个贡献就是这一位及前面一共有多少1,为什么呢?考虑a=1001和b=10101,那么a的第四位一共要&三次b的1,值为1,所以答案就是每一位十进制的值*这一位的贡献,注意用前缀和预处理一下b的1的个数。

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const int maxn=200005;
const int mod=998244353;
const double eps=1e-8;
const double PI = acos(-1.0);
#define lowbit(x) (x&(-x))
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll qpow(ll a,ll b){ll t=1;while(b){if(b%2){t=(t*a)%mod;b--;}a=(a*a)%mod;b/=2;}return t;}
int main()
{
    std::ios::sync_with_stdio(false);
    int n,m;
    string a,b;
    while(cin>>n>>m)
    {
        cin>>a>>b;
        if(n<m)
        {
            a=string(m-n,'0')+a;
        }
        else
        {
            b=string(n-m,'0')+b;
        }
        n=max(n,m);
        ll sum[maxn]={0};
        sum[0]=(b[0]=='1');
        for(int i=1;i<n;i++)
        {
            sum[i]=sum[i-1]+(b[i]=='1');
        }
        ll ans=0;
        for(int i=0;i<n;i++)
        {
            ll res=(a[i]=='1');
            if(res)
            res=qpow(2,n-i-1);
            ans=(ans+(res*sum[i])%mod)%mod;
        }
        cout<<ans<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Dilly__dally/article/details/83064590