[cf 1245 F] Daniel and Spring Cleaning

题意:

求区间$[l,r]$内有多少有序数对$(a,b)$满足$a+b=a\bigoplus b$。

$l,r\leq 10^9$。

 

题解:

  • 求区间内一元组可以一维容斥,同理求二元组可以二维容斥,三元组可以三维容斥……
  • 数位dp可以一堆数一起dp,每次考虑的位一样就行。

 

代码:

#include<bits/stdc++.h>
#define maxn 55
#define maxm 500005
#define inf 0x7fffffff
#define ll long long
 
using namespace std;
ll dp[maxn][2][2][2][2],d1[maxn],d2[maxn];
 
inline ll read(){
    ll x=0,f=1; char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    return x*f;
}
 
inline ll dfs(ll now,int t1,int t2,int q1,int q2){
    if(now==-1) return 1;
    if(dp[now][t1][t2][q1][q2]!=-1) return dp[now][t1][t2][q1][q2];
    int u1=t1?d1[now]:1,u2=t2?d2[now]:1; ll res=0;
    for(int i=0;i<=u1;i++)
        for(int j=0;j<=u2;j++){
            if(i==1 && j==1) continue;
            int nt1=t1&&(i==u1);
            int nt2=t2&&(j==u2);
            int nq1=q1||(i==1);
            int nq2=q2||(j==1);
            res+=dfs(now-1,nt1,nt2,nq1,nq2);
        }
    dp[now][t1][t2][q1][q2]=res;
    return res;
}
 
inline ll calc(ll x,ll y){
    if(x<0 || y<0) return 0;
    memset(dp,-1,sizeof(dp));
    for(ll i=0;i<=30;i++) d1[i]=((x>>i)&1);
    for(ll i=0;i<=30;i++) d2[i]=((y>>i)&1);
    return dfs(30,1,1,0,0);
}
 
int main(){
    ll T=read();
    while(T--){
        ll l=read(),r=read();
        printf("%I64d\n",calc(r,r)-2*calc(l-1,r)+calc(l-1,l-1));
    }
    return 0;
}
F
posted @ 2019-11-03 10:23  Fugtemypt  阅读(277)  评论(0编辑  收藏  举报