Google Code Jam 2014 Round 1B Problem B

二进制数位DP,涉及到数字的按位与操作。

查看官方解题报告

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
using namespace std;

#define MAX_LEN 50

long long A, B, K;
int a[MAX_LEN], b[MAX_LEN], k[MAX_LEN];
long long memoize[MAX_LEN][2][2][2];

void input()
{
    scanf("%lld%lld%lld", &A, &B, &K);
}

int convert(long long A, int a[])
{
    int i = 0;
    while (A)
    {
        a[i] = A & 1;
        A >>= 1;
        i++;
    }
    return i;
}

long long dfs(int current_bit, bool less_a, bool less_b, bool less_k)
{
    if (current_bit == -1)
    {
        if (less_a && less_b && less_k)
        {
            return 1;
        }
        return 0;
    }
    if (memoize[current_bit][less_a][less_b][less_k] != -1)
        return memoize[current_bit][less_a][less_b][less_k];
    bool one_a = less_a || a[current_bit] == 1;
    bool one_b = less_b || b[current_bit] == 1;
    bool one_k = less_k || k[current_bit] == 1;
    // a0 b0
    long long ret = dfs(current_bit - 1, one_a, one_b, one_k);
    // a1 b0
    if (one_a)
    {
        ret += dfs(current_bit - 1, less_a, one_b, one_k);
    }
    // a0 b1
    if (one_b)
    {
        ret += dfs(current_bit - 1, one_a, less_b, one_k);
    }
    // a1 b1
    if (one_a && one_b && one_k)
    {
        ret += dfs(current_bit - 1, less_a, less_b, less_k);
    }
    return memoize[current_bit][less_a][less_b][less_k] = ret;
}

int main()
{
    int t;
    scanf("%d", &t);
    for (int i = 0; i < t; i++)
    {
        printf("Case #%d: ", i + 1);
        input();
        memset(a, 0, sizeof(a));
        memset(b, 0, sizeof(b));
        memset(k, 0, sizeof(k));
        convert(A, a);
        convert(B, b);
        convert(K, k);
        memset(memoize, -1, sizeof(memoize));
        long long ans = dfs(31, false, false, false);
        printf("%lld
", ans);
    }
    return 0;
}
View Code