Sum of Log 题解(数位dp)

题目链接

题目思路

首先\(log(i+j)\)只和\(i+j\)化为二进制的最高位有关

并且\(i\&j=0\) 所以不会有进位,那么就是和\(i,j\)中的二进制最高位的最高位有关

然后就是数位\(dp\)

设的是\(dp[pos][p][lim1][lim2]\)

\(pos\)的位置最高位位\(p\),以及\(i,j\)是否有限制了 但是这样会\(tle\)

要把\(p\)改为是否当前为1,并且以前没有1出现过

说是套路数位\(dp\),但是我不会啊...

代码

#include<bits/stdc++.h>
#define fi first
#define se second
#define debug cout<<"I AM HERE"<<endl;
using namespace std;
typedef long long ll;
const int maxn=2e5+5,inf=0x3f3f3f3f,mod=1e9+7;
const double eps=1e-6;
int x,y;
int a[40],b[40];
ll dp[32][2][2][2];
ll ans;
ll dfs(int pos,int flag,int lim1,int lim2){
    if(pos==-1){
        return 1;
    }
    if(dp[pos][flag][lim1][lim2]!=-1){
        return dp[pos][flag][lim1][lim2];
    }
    int up1=(lim1?a[pos]:1);
    int up2=(lim2?b[pos]:1);
    ll num=0;
    for(int i=0;i<=up1;i++){
        for(int j=0;j<=up2;j++){
            if(i&j) continue;
            ll tmp=dfs(pos-1,flag||i||j,lim1&&i==a[pos],lim2&&j==b[pos]);
            if(!flag&&(i||j)){
                ans+=1ll*(pos+1)*tmp%mod;
                ans%=mod;
            }
            num+=tmp;
            num%=mod;
        }
    }
    return dp[pos][flag][lim1][lim2]=num;
}
void solve(int x,int y){
    ans=0;
    memset(dp,-1,sizeof(dp));
    memset(a,0,sizeof(a));
    memset(b,0,sizeof(b));
    for(int i=0;i<=30;i++){
        if((x>>i)&1) a[i]=1;
        if((y>>i)&1) b[i]=1;
    }
    dfs(30,0,1,1);
    printf("%lld\n",ans);
}
signed main(){
    int _;scanf("%d",&_);
    while(_--){
        scanf("%d%d",&x,&y);
        solve(x,y);
    }
    return 0;
}

posted @ 2021-11-02 00:09  hunxuewangzi  阅读(105)  评论(0编辑  收藏  举报