bzoj 4918: 回文数对

传送门

Description

给定区间[L,R],请统计有多少对整数A,B(L<=A,B<=R)满足A xor B的值在二进制表示下,去掉所有前导0后是回文串

Input

第一行包含一个正整数T(1<=T<=100),表示测试数据的组数。
每组数据包含一行两个整数L,R(0<=L<=R<=10^12),含义如题面所述。

Output

对于每组数据输出一行一个整数,即满足条件的整数对个数。
 
 
反正就是数位dp,从两端往中间跑,记录下大小关系,谁都会写。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;

ll n,m,T,f[51][16];
ll min(ll a,ll b){return a<b?a:b;}
ll work(ll n,ll a,ll b){
    ll MMH=0;
    memset(f,0,sizeof(f));
    f[0][3]=1;
    for (ll i=1;i<=(n>>1);i++)
    for (ll qa=0;qa<2;qa++)
    for (ll qb=0;qb<2;qb++)
    for (ll ha=0;ha<2;ha++)
    for (ll hb=0;hb<2;hb++)
    if ((qa^qb)==(ha^hb)&&(i!=1||qa!=qb)){
        ll QA=(a>>n-i)&1,QB=(b>>n-i)&1;
        ll HA=(a>>i-1)&1,HB=(b>>i-1)&1;
        
        for (ll k=0;k<16;k++){
            ll K=k;
            if (QA<qa&&!(k&8)) continue;
            if (QB<qb&&!(k&4)) continue;
            
            if (QA>qa) K|=8;
            if (QB>qb) K|=4;
            
            if (HA>ha) K|=2;else if (HA<ha) K&=13;
            if (HB>hb) K|=1;else if (HB<hb) K&=14;
            f[i][K]+=f[i-1][k];
        }
    }
    
    if (n&1){
        ll i=n+1>>1;
        for (ll _a=0;_a<2;_a++)
        for (ll _b=0;_b<2;_b++)
        if (n!=1||_a!=_b){
            ll A=(a>>i-1)&1,B=(b>>i-1)&1;
            
            for (ll k=0;k<16;k++){
                ll K=k;
                if (A<_a&&!(k&8)) continue;
                if (B<_b&&!(k&4)) continue;
                
                if (A>_a) K|=8;
                if (B>_b) K|=4;
                f[i][K]+=f[i-1][k];
            }
        }
    }
    ll i=n+1>>1;
    for (ll k=0;k<16;k++)
    if (((k&8)||(k&2))&&((k&4)||(k&1))) MMH+=f[i][k];
    return MMH;
}
ll Mavis(ll a,ll b){
    if (b<0) return 0;
    ll i,j,k,mmh=0;
    for (i=40,j=0,k=0;i;i--){
        j<<=1;k<<=1;j|=(a>>i)&1;k|=(b>>i)&1;
        if (j==k) mmh+=j*work(i,(1ll<<i)-1,(1ll<<i)-1)+work(i,a&((1ll<<i)-1),b&((1ll<<i)-1));else mmh+=k*work(i,(1ll<<i)-1,(1ll<<i)-1)+work(i,(1ll<<i)-1,b&((1ll<<i)-1));
    }
    return mmh+b+1;
}
int main(){
    scanf("%lld",&T);
    while(T--){
        scanf("%lld%lld",&n,&m);
        printf("%lld
",Mavis(m,m)-2*Mavis(m,n-1)+Mavis(n-1,n-1));
    }
}
View Code
原文地址:https://www.cnblogs.com/Enceladus/p/7124355.html