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
",ans);
}
signed main(){
    int _;scanf("%d",&_);
    while(_--){
        scanf("%d%d",&x,&y);
        solve(x,y);
    }
    return 0;
}

不摆烂了,写题
原文地址:https://www.cnblogs.com/hunxuewangzi/p/15496858.html