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;
}
不摆烂了,写题