题意:
对于16进制数字num,假定 $p_0,p_1,...,p_m$ 在该数字中出现过,如果有 $x = 2^{p_0} + 2^{p_1} + ... + 2^{p_m}$
且 $x oplus num < num$ 则认为 $F(num) = 1$, 不然 $F(num) = 0$
求$sum_{i=L}^R {F(i)}$
解法:
考虑 $F(num) = 1$ 的条件,注意到如果有 $x oplus num < num$,相当于 $num$ 二进制的 $p_m$ 位为1。
这样考虑数位dp。
对于确定位,我们记一下最大值。
对于不确定位,我们枚举一下全局最大值 $p_m$,然后枚举一下 $p_m / 4 +1$ 位可以的16进制的值,然后快速幂+容斥算一下即可。

#include <iostream> #include <cstdio> #include <cstring> #define LL long long #define N 110 #define bit(t) (1<<(t)) using namespace std; int q,num[N],dig[N]; LL qpow(LL x,int n) { LL ans=1; for(;n;n>>=1,x=x*x) if(n&1) ans=ans*x; return ans; } LL calc(int m,int tot,int maxnow) { LL ans=0; for(int t=15;t>=maxnow;t--) { int x = t/4+1; int tmp = t%4; if(x > tot) continue; for(int S=0;S<(1<<3);S++) { int now=bit(tmp); for(int i=0;i<3;i++) if(bit(i)&S) now|=bit((tmp+i+1)%4); if(now > t || (dig[x]!=-1 && dig[x]!=now)) continue; int cnt=m; if(dig[x]==-1) cnt--; if(now == t || maxnow == t) ans += qpow(t+1, cnt); else ans += qpow(t+1, cnt) - qpow(t, cnt); } } return ans; } LL calc(char *S,bool inc) { memset(num,0,sizeof(num)); int tot=strlen(S); for(int i=0;i<tot;i++) { if(S[i]<='9' && S[i]>='0') num[tot-i] = S[i]-'0'; else num[tot-i] = S[i]-'a'+10; } if(inc) { num[1]++; for(int i=1;i<=tot;i++) if(num[i]>=16) num[i]-=16,num[i+1]++; if(num[tot+1]) tot++; } for(int i=1;i<=tot;i++) dig[i]=-1; LL ans = 0; int maxnow=0; for(int i=tot;i>=1;i--) { for(int j=0;j<num[i];j++) dig[i]=j, ans += calc(i-1, tot, max(maxnow,j)); dig[i]=num[i]; maxnow=max(maxnow,dig[i]); } return ans; } char L[N],R[N]; int main() { int q; cin>>q; while(q--) { cin>>L>>R; cout<<calc(R,1)-calc(L,0)<<endl; } return 0; }