ARC 066D Xor Sum

92 篇文章 0 订阅
86 篇文章 0 订阅

因为a xor b = a + b - 2 (a & b)
从低位到高位用记忆化搜索实现数位DP

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
#define LL long long
#define mod 1000000007
#define hmod 300007
using namespace std;

LL n;
int info[300007],Prev[1000000],val[1000000],cnt_e;
LL key[2][1000000];

int Insert(LL u,LL v,int cst)
{
    int k = (u % hmod + v % hmod) % hmod;
    if(cst==-1)
    {
        for(int i=info[k];i;i=Prev[i])
            if(key[0][i] == u && key[1][i] == v)
                return val[i];
        return -1;
    }
    else Prev[++cnt_e] = info[k] , info[k] = cnt_e , val[cnt_e] = cst , key[0][cnt_e] = u , key[1][cnt_e] = v;
}

int dfs(LL u,LL v)
{
    if(v<0) return 0;
    if(v==0) return 1;
    LL tmp;
    if((tmp=Insert(u,v,-1))!=-1) return tmp;
    tmp = ((dfs(u >> 1 ,v >> 1) + dfs((u-1) >> 1 , (v-1) >> 1)) % mod + dfs(u>>1 , (v-2)>>1)) % mod;
    // 从低到高枚举数位,三种情况:a & 1 == b & 1 = 0 , (a & 1 == 1) ^ (b & 1 == 1) = 1 , a & 1 == b & 1 = 1
    Insert(u,v,tmp);
    return tmp;
}

int main()
{
    scanf("%lld",&n);
    printf("%d",dfs(n,n));
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值