因为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));
}