Google Code Jam Round1B B题

水完小数据后,仔细想了想,绝对的数位DP啊,我去。

推式子,写代码,一气呵成啊我去,结果坑在memset上了我去,还不如让我没有思路。

上图。。



可以看到sizeof(num) == 4,sizeof(w) == 52。

也就是说此时num虽然也指向w[0]。但是仅代表着w[0]这个元素,并不代表这个数组。

先暂且这样理解着吧,坐等大神来指导。


好了废话不说了,很简单的数位DP,发在这里只是为了提醒一下memset,不是自己写的函数要慎用啊。


#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
#include <stack>
#include <map>

#pragma comment(linker, "/STACK:1024000000");
#define EPS (1e-8)
#define LL long long
#define ULL unsigned long long LL
#define _LL __int64
#define _INF 0x3f3f3f3f
#define Mod 1000000007
#define LM(a,b) (((ULL)(a))<<(b))
#define RM(a,b) (((ULL)(a))>>(b))

using namespace std;

LL dp[35][2][2][2];

int a[35],b[35],k[35];

int Init(int *num,LL x)
{
    int len = 0;

    LL temp = x;

    while(temp)
    {
        ++len;
        temp /= 2;
    }

    int i;

    temp = x;

    for(i = 0; i < len; ++i)
    {
        num[32-i] = temp%2;
        temp /= 2;
    }
    return len;
}

LL dfs(bool ta,bool tb,bool tk,int site,int Top)
{
    int sa = (ta == true ? 1 : 0);
    int sb = (tb == true ? 1 : 0);
    int sk = (tk == true ? 1 : 0);
    if(site == Top+1)
    {
        return 1;
    }

    if(dp[site][sa][sb][sk] != -1)
        return dp[site][sa][sb][sk];

    LL ans = 0;

    int pa,pb,i,j;

    if(tk == true)
    {
        if(k[site] == 1)
        {
            if(a[site] == 1 || ta == false)
                pa = 1;
            else
                pa = 0;

            if(b[site] == 1 || tb == false)
                pb = 1;
            else
                pb = 0;

            for(i = 0; i <= pa; ++i)
            {
                for(j = 0; j <= pb; ++j)
                {
                    ans += dfs(ta && i == pa ,tb && j == pb,tk && (i&j) == k[site],site+1,Top);
                }
            }
        }
        else
        {
            if(a[site] == 1 || ta == false)
                pa = 1;
            else
                pa = 0;

            if(b[site] == 1 || tb == false)
                pb = 1;
            else
                pb = 0;

            for(i = 0; i <= pa; ++i)
            {
                for(j = 0; j <= pb; ++j)
                {
                    if((i&j) == 0)
                    {
                        ans += dfs(ta && i == pa ,tb && j == pb,true,site+1,Top);
                    }
                }
            }
        }
    }
    else
    {
        if(a[site] == 1 || ta == false)
            pa = 1;
        else
            pa = 0;

        if(b[site] == 1 || tb == false)
            pb = 1;
        else
            pb = 0;

        for(i = 0; i <= pa; ++i)
        {
            for(j = 0; j <= pb; ++j)
            {
                ans += dfs(ta && i == pa ,tb && j == pb,false,site+1,Top);
            }
        }
    }
    dp[site][sa][sb][sk] = ans;
    return ans;
}

LL Cal(LL A,LL B,LL K)
{
    memset(a,0,sizeof(a));
    memset(b,0,sizeof(b));
    memset(k,0,sizeof(k));

    int la = Init(a,A);
    int lb = Init(b,B);
    int lk = Init(k,K);

    if(la == 0)
        la = 1;

    if(lb == 0)
        lb = 1;

    if(lk == 0)
        lk = 1;

    int L = max(la,max(lb,lk));

    memset(dp,-1,sizeof(dp));

    return dfs(true,true,true,32-L+1,32);
}

int main()
{
    //freopen("B-large-practice.in","r",stdin);
    //freopen("B-large-practice.out","w",stdout);

    
    LL a,b,k;

    int T;

    scanf("%d",&T);

    int icase = 1;

    while(T--)
    {
        scanf("%lld %lld %lld",&a,&b,&k);

        a--,b--,k--;
        printf("Case #%d: ",icase++);
        cout<<Cal(a,b,k)<<endl;
    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值