zoukankan      html  css  js  c++  java
  • 51nod-1232: 完美数

    【传送门:51nod-1232


    简要题意:

      完美数定义:一个数能够被它每一位非零的数整除,例如:11,12,15,但13就不是完美数,因为13不能被3整除

      给出T组询问,每组询问输入l,r,输出l到r中有多少个完美数


    题解:

      首先很容易想到只要当前数被每一位所有非零的数的lcm整除就好了

      实际上最大的lcm只有2520,而且只能够构成48个不同lcm的值

      那么就可以利用这个来节省空间了,将lcm离散编号

      设f[i][j][k]为第i位已经填好数字后,当前构成的数%2520=j,且当前数位的数的lcm的离散编号为k

      然后直接记忆化搜索就行了


    参考代码:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    typedef long long LL;
    LL f[21][3100][51];
    int p[3100],Mod=2520;
    void pre()
    {
        int k=0;p[0]=0;
        for(int i=1;i<=Mod;i++) if(Mod%i==0) p[i]=++k;
    }
    int cnt[21],tot;
    int gcd(int a,int b)
    {
        if(a==0) return b;
        else return gcd(b%a,a);
    }
    int getd(int a,int b)
    {
        if(a==0) return b;
        if(b==0) return a;
        return a*b/gcd(a,b);
    }
    LL dfs(int tp,int x,int d1,int d2)
    {
        if(x==1)
        {
            if(d2==0) return 0;
            return d1%d2==0;
        }
        if(tp==0&&f[x][d1][p[d2]]!=-1) return f[x][d1][p[d2]];
        if(tp==0)
        {
            f[x][d1][p[d2]]=0;
            for(int i=0;i<=9;i++)
            {
                if(i==0) f[x][d1][p[d2]]+=dfs(tp,x-1,(d1*10+i)%Mod,d2);
                else f[x][d1][p[d2]]+=dfs(tp,x-1,(d1*10+i)%Mod,getd(d2,i));
            }
            return f[x][d1][p[d2]];
        }
        else
        {
            LL ans=0;
            for(int i=0;i<=cnt[x-1];i++)
            {
                if(cnt[x-1]==0) ans+=dfs(tp,x-1,(d1*10+i)%Mod,d2);
                else if(i==0) ans+=dfs(tp^1,x-1,(d1*10+i)%Mod,d2);
                else if(i==cnt[x-1]) ans+=dfs(tp,x-1,(d1*10+i)%Mod,getd(d2,i));
                else ans+=dfs(tp^1,x-1,(d1*10+i)%Mod,getd(d2,i));
            }
            return ans;
        }
    }
    LL solve(LL x)
    {
        if(x==0) return 0;
        LL d=x;tot=0;
        while(d!=0){cnt[++tot]=d%10;d/=10;}
        LL ans=0;
        for(int i=0;i<=cnt[tot];i++)
        {
            if(i==0) ans+=dfs(0,tot,0,0);
            else if(i==cnt[tot]) ans+=dfs(1,tot,i,i);
            else ans+=dfs(0,tot,i,i);
        }
        return ans;
    }
    int main()
    {
        pre();
        int T;
        scanf("%d",&T);
        memset(f,-1,sizeof(f));
        while(T--)
        {
            LL l,r;
            scanf("%lld%lld",&l,&r);
            printf("%lld
    ",solve(r)-solve(l-1));
        }
        return 0;
    }

     

  • 相关阅读:
    存储型 XSS 原理复现
    反射型 XSS 原理复现
    HTTP 简易理解
    Markdown 流程图语法
    Dirsearch 快速开始
    sqlmap 快速开始
    SQL 注入原理
    XSS 原理
    51nod 1835 完全图
    11.5 AM 请求
  • 原文地址:https://www.cnblogs.com/Never-mind/p/9875276.html
Copyright © 2011-2022 走看看