1. 程式人生 > >Codeforces Round #515 (Div. 3) E(模擬+字首和)

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;
}