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\n", ans);
    }
    return 0;
}

时间: 2024-10-06 08:22:48

Google Code Jam 2014 Round 1B Problem B的相关文章

Google Code Jam 2014 Round 2回顾和分析

回顾 比赛开始网络就一直在抽风,不知道宿舍网渣还是有人攻击服务器.刷了n遍n久刷出了题目.提交A小case的时候眼睁睁看着时间过去,却提交不上,这破网.最后A题B题还是解决了,C题扫了一眼,读都没读,就奔D题去了,因为我看到了熟悉的trie这个单词,加之看到小case只有9分,判断小case应该比较容易.前面因为网络浪费了很多时间,加之从未编过trie的程序,只能临时上网翻书去学,最后D小这个可以很容易暴力解的问题也没编完. 最终的rank是13xx,考虑到在这次GCJ之前从未接触过编程竞赛,而

Google Code Jam 2016 Round 1B B

题意:给出两个数字位数相同,分别中间有若干位不知道,用问号表示.现在要求补全这两个数字,使得差值的绝对值最小,多解则取第一个数字的值最小的,再多解就取第二个数字最小的. 分析: 类似数位dp,但是很多状态可以直接得出最终解,个别状态需要状态转移. 我们从高位到低位依次确定两个数的每个位是几.一旦确定了两个数的一个位不一样,则可以立即将小的一方的后续问号全部写9,大的一方后续问号全部写0.这样才能让差值最小. 那我们观察每个位的时候要如何确定其值呢?分如下几种情况. 1.两个数的该位都是问号,那么

Google Code Jam 2009, Round 1C C. Bribe the Prisoners (记忆化dp)

Problem In a kingdom there are prison cells (numbered 1 to P) built to form a straight line segment. Cells number i and i+1 are adjacent, and prisoners in adjacent cells are called "neighbours." A wall with a window separates adjacent cells, and

Google Code Jam 2014 Round2

Google Code Jam Round2 晚上10点开始的,开始google一直上不去,然后开了个vpn就行了. 说说我的情况吧. P1就是某年noip普及组纪念品分组,贪心. p2是说给你一个排列,然后每次可以交换两个相邻的数,使得最后序列变为先上升后下降的样子.(n<=1000) 一开始题目看错了,以为是交换任意两个,然后愣了半天不会,去写后两题暴力了. (话说我Round1Cp1题目也看错了害的我逗了好久) 后来突然发现是adjacent elements...(<论英语学习的重要性

Google Code Jam 2014 总结

已经辞了,人也离开帝都了.是否还会回去? 不知道,也许脑子突然正常了又跑回去了. 如题,继续不温不火的Windows Phone. 今年2014,没错,Windows Phone是新加了好几家厂商,微软也有了更大的改变.常刷微博,看到好些人说,今年是Windows Phone年.Maybe..那么多厂商其实还是有些在观望,没啥很大的实际行动. 上次纯粹是抱怨了. 好多人评论说坚持.坚持.坚持的. Thank you.离开帝都前,参加了微软的全球开发者马拉松比赛,运气好,再加上同事的帮忙,捡了一部

Google Code Jam 2019 Round 1A 题解

A. Alien Rhyme 题意: 思路:将字符反向插入一颗Trie,然后自下而上的贪心即可,即先选后缀长的,再选后缀短的. 实现: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <iomanip> 5 6 #include <vector> 7 #include <cstring> 8 #include <string>

Google Code Jam 2016 Round 1C C

题意:三种物品分别有a b c个(a<=b<=c),现在每种物品各选一个进行组合.要求每种最和最多出现一次.且要求任意两个物品的组合在所有三个物品组合中的出现总次数不能超过n. 要求给出一个方案,使得我们能够生成的组合数最多. 分析: 首先我们可以简单的处理一种情况,就是c<=n的情况. 因为我们枚举出了所有组合,那么两物品的出现次数的最大值不会超过c,因为A种和B种的每对组合都会在其中出现c次,其余两个的组合出现次数更少. 所以这种情况一定不会超过n,我们只需要枚举所有组合即可. 然而

2015 Google code jam Qualification Round B 枚举 + 贪心

题意:给你一个无穷长的数列 和一些非 0 的值,可以进行两种操作. 1)数列中所有大于1的值 都减1 2)从 a[i] 中取出任意的值分给任意人. 问你最少执行多少步能使的 数列全为0. 解题思路:枚举最大的a[i].大于 a[i]的部分都分出去. 解题代码: 1 // File Name: b.cpp 2 // Author: darkdream 3 // Created Time: 2015年04月11日 星期六 23时16分58秒 4 5 #include<vector> 6 #incl

Google Code Jam 2015 Round 1A Mushroom Monster 水

题意:每10秒扫描一下盘子,查看盘子里面的面包个数,问你主角用两种吃法可能吃得的最少的面包. 1)任意吃. 2)每秒以恒定速度. 解题思路:暴力,找差值. 解题代码: 1 // File Name: a.cpp 2 // Author: darkdream 3 // Created Time: 2015年04月18日 星期六 09时52分04秒 4 5 #include<vector> 6 #include<list> 7 #include<map> 8 #includ