[2020 ICPC 上海 C] Sum of Log

https://ac.nowcoder.com/acm/contest/9925/C
题意:
\(10^5\)组数据中,每组给定两个非负整数\(X,Y(X,Y \leq 10^9)\)\(\sum_{i = 0}^X\sum_{j=[i=0]}^Y[i\&j=0][log_2(i+j)+1]\)

思路:
很容易想到在二进制下进行数位\(dp\),传递枚举到的位置,第一个出现\(1\)的位置,以及\(X\)\(Y\)是否达到上边界。但是这样时间复杂度达到了\(O(T * 30 * 30 * 2 * 2)\),虽然只要初始化得好的话牛客上抖一抖和CF的机子上能刚好跑过去,但是时间复杂度是可以优化的。我们发现当第一个出现\(1\)的位置在前面确定之后,后面所有数字能产生的贡献都是一样的,所以如果我们把dp数组里传递的值从产生的贡献改成能产生贡献的数量,就可以把时间复杂度降到\(O(T * 30 * 2 * 2 * 2)\)

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

template <class T> inline void read(T &x) {
    int f = 0; x = 0; char ch = getchar();
    for (; !isdigit(ch); ch = getchar()) f |= (ch == '-');
    for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
    if (f) x = -x;
}

const int N = 32;
const ll mod = 1e9 + 7;

int dp[N][2][2][2];
int tot1, tot2, dig1[N], dig2[N];
int x, y, ans;

void add(int &a, int b) {
    a += b;
    if (a >= mod) a -= mod;
}

int dfs(int pos, bool lim1, bool lim2, bool ok) {
    if (pos == -1) return ok;
    if (dp[pos][lim1][lim2][ok]) return dp[pos][lim1][lim2][ok];
    int to1 = lim1? dig1[pos] : 1;
    int to2 = lim2? dig2[pos] : 1;
    int tmp = 0;
    for (int i = 0; i <= to1; ++i) {
        for (int j = 0; j <= to2; ++j) {
            if (i && j) continue;
            int num = dfs(pos - 1, lim1 && i == to1, lim2 && j == to2, ok || i || j);
            add(tmp, num);
            if (!ok && (i || j)) add(ans, (ll)num * (ll)(pos + 1) % mod);
        }
    }
    return dp[pos][lim1][lim2][ok] = tmp;
}

void calc(int x, int y) {
    int len = 0;
    memset(dig1, 0, sizeof(dig1));
    memset(dig2, 0, sizeof(dig2));
    while (x) {
        dig1[len++] = x & 1;
        x >>= 1;
    }
    len = 0;
    while (y) {
        dig2[len++] = y & 1;
        y >>= 1;
    }
    dfs(30, true, true, false);
}

void solve() {
    ans = 0;
    memset(dp, 0, sizeof(dp));
    scanf("%d %d", &x, &y);
    calc(x, y);
    printf("%d\n", ans);
}

int main() {
    int t = 1;
    scanf("%d", &t);
    while (t--) solve();
    return 0;
} 
posted @ 2021-03-07 15:15  stff577  阅读(203)  评论(0)    收藏  举报