zoukankan      html  css  js  c++  java
  • Sherlock and the Encrypted Data

    题意:

    对于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;
    }
    View Code
  • 相关阅读:
    MicroPython实例之TPYBoard v102炫彩跑马灯WS2812B
    MicroPython实例之TPYBoardv102自动浇花系统
    Micropython实例之DIY超声波避障小车
    MicroPython支持图形化编辑了:Python Editor带你轻松玩转MicroPython
    潍坊首个小学“教育创客空间”落户呼家庄小学 萝卜(创客)教育走进小学课堂
    Micropython TPYBoard I2C的用法
    JDK5.0新特性-反射
    JDK5.0新特性-枚举
    JDK5.0新特性-泛型
    JDK5.0新特性-静态导入
  • 原文地址:https://www.cnblogs.com/lawyer/p/6841820.html
Copyright © 2011-2022 走看看