codeforces597 div2 F 数位dp
题意:
求[L,R]中a&b==0的“对数”
思路:
一个典型的求“对数”的数位dp,对比普通的数位dp,共用一个pos,维护两个limit。剩下的就是“暴搜”了,当然注意去重,因为是求对数就不是简单的\(ans_{R}-ans_{L-1}\)了。还有要注意lim的状态也要保存,不然会超时。
代码:
#include <bits/stdc++.h> using namespace std; #define X first #define Y second #define PB push_back #define LL long long #define pii pair<int,int> #define MEM(x,y) memset(x,y,sizeof(x)) #define bug(x) cout<<"debug "#x" is "<<x<<endl; #define FIO ios::sync_with_stdio(false); #define ALL(x) x.begin(),x.end() #define LOG 20 const int inf =1e9; const int maxn =3e5+7; const int mod = 1e9+7; LL dp[35][2][2]; LL solve(int L,int R,int pos,int lim1,int lim2){ if(pos<0) return 1; if(dp[pos][lim1][lim2]!=-1) return dp[pos][lim1][lim2]; int up1=lim1?((L>>pos)&1):1,up2=lim2?((R>>pos)&1):1; dp[pos][lim1][lim2]=0; for(int i=0;i<=up1;i++)for(int j=0;j<=up2;j++) if((i&j)==0) dp[pos][lim1][lim2]+=solve(L,R,pos-1,lim1&&i==up1,lim2&&j==up2); return dp[pos][lim1][lim2]; } LL do_solve(int l,int r){ if(l<0||r<0) return 0; MEM(dp,-1); return solve(l,r,31,1,1); } int main(){ FIO; int t,l,r; cin>>t; while(t--){ MEM(dp,-1); cin>>l>>r; cout<<do_solve(r,r)-do_solve(l-1,r)*2+do_solve(l-1,l-1)<<endl; } return 0; }