天天看點

CodeForces - 1066E Binary Numbers AND Sum(字首和)

哎…這道題一言難盡啊,從一開始的想法逾時到慢慢分析知道了字首和,在到出現了bug,電腦前一坐就是3個小時、

嘛。最近的題隻要做出來都是熬出來的…哎…越發開始懷疑人生

CodeForces - 1066E Binary Numbers AND Sum(字首和)

廢話少說,題意看樣例也能猜出來想幹什麼

如果按模拟來的話,一個一個來每次相應的10進制肯定會逾時(我也親身體驗了)

題目上說每次 b/2 ,不過其意思從樣例也可以看出隻是向右移了一位

是以我們要找個方法把每次(b >> 1 )& a 的和直接求出來。

這裡就需要一個字首和。

先看這個圖:

CodeForces - 1066E Binary Numbers AND Sum(字首和)

這是第一個樣例b每次右移的結果。

從左到右對應着二進制換成10進制的(8,4,2,1)

橫線下面的1 2 2 3 代表8 4 2 1分别有幾個。

再加上&a,這個樣例的a為1010

即 1 * 8 * 1 + 0 * 4* 2 + 1 * 2 * 2 + 0 * 1 * 3 = 8 + 0 + 4 + 0 = 12。

這樣就可以直接求出來a&b的結果。

而對于1 2 2 3的求法從下往上看和從左往右看是一樣的。也就是字首和的求法了

具體怎麼操作可以看看這裡,随便了解一下字首和還有其他好用的地方:https://blog.csdn.net/whxntj/article/details/54619204

關鍵的都講完了,其他的都很好操作了。不過有一點要注意的是,,,

哎,這個數太大了。以至于出現了一個bug耽誤了老長時間。

最後也知道原因了,什麼情況看聊天記錄吧

CodeForces - 1066E Binary Numbers AND Sum(字首和)
CodeForces - 1066E Binary Numbers AND Sum(字首和)
CodeForces - 1066E Binary Numbers AND Sum(字首和)
CodeForces - 1066E Binary Numbers AND Sum(字首和)

下面是ac代碼:

#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
const int maxn = 200020;
const long mod = 998244353;
char a[maxn], b[maxn];
int prefix[maxn];
int n, m;
inline ll B_D(int j, int i)
{
    ll B = 1, ans = 0;
    while(i&&j)
    {
        ans += ((a[j--]-'0')*B*prefix[i--])%mod;
        B = (B*2)%mod;
    }
    return ans%mod;
}
int main()
{
    cin >> n >> m;
    scanf("%s%s",a+1,b+1);
    for(int i = 1; i <= m; ++i)
        prefix[i] += prefix[i-1]+(b[i]-'0');
    cout << B_D(n,m)%mod << endl;
    return 0;
}