2014 GCJ Round 1B New Lottery Game(数位dp,x小于等于A,y小于等于B,并且x&y值小于等于K的数字个数)

来源:互联网 发布:个人网上开店平台 知乎 编辑:程序博客网 时间:2024/04/29 21:27

题目链接:
2014 GCJ Round 1B New Lottery Game
题意:
xA,yB,并且x&y值小于等于K的数字个数。
数据范围:A,B,K109
分析:
官方题解在这里:Here。通篇读下来很有意思,对于理解数位dp很有帮助。

一般的数位dp我们在dfs的时候只记录一个limit表示是否达到区间上限,这里我们需要记录三个,因为x,y和二进制与出来的值都有上限。

// GCJ 2014 #Round1B New Lottery Game//https://code.google.com/codejam/contest/2994486/dashboard#s=p1&a=1#include <stdio.h>#include <string.h>#include <math.h>#include <algorithm>using namespace std;typedef long long ll;int T, cases = 0;ll A, B, K;ll vis[35][3][3][3];ll solve(int cur, int lessA, int lessB, int lessK){    if (cur == -1) return lessA && lessB && lessK;    if (vis[cur][lessA][lessB][lessK] != -1) return vis[cur][lessA][lessB][lessK];     int MaxA = lessA || ((A >> cur) & 1);    int MaxB = lessB || ((B >> cur) & 1);    int MaxK = lessK || ((K >> cur) & 1);    ll ret = solve(cur - 1, MaxA, MaxB, MaxK); // 0 & 0 = 0     if (MaxA) ret += solve(cur - 1, lessA, MaxB, MaxK); // 0 & 1 = 0     if (MaxB) ret += solve(cur - 1, MaxA, lessB, MaxK); // 1 & 0 = 0     if (MaxA && MaxB && MaxK) ret += solve(cur - 1, lessA, lessB, lessK); // 0 & 0 = 0    return vis[cur][lessA][lessB][lessK] = ret;}int main(){    scanf("%d", &T);    while (T--) {        scanf("%lld%lld%lld", &A, &B, &K);        memset(vis, -1, sizeof(vis));        printf("Case #%d: %lld\n", ++cases, solve(31, 0, 0, 0));    }    return 0;}
0 0
原创粉丝点击