• FZU2179(数位dp)


    传送门:Chriswho

    题意:求区间[1,n]内能整除自己本身各位数字的数的个数。

    分析:这题跟CF 55D Beautiful numbers一样的,一个数能被它的所有非零数位整除,则能被它们的最小公倍数整除,而1到9的最小公倍数为2520,为了判断这个数能否被它的所有数位整除,我们还需要这个数的值,但这里我们只需记录它对2520的模即可,dp[pos][sum][lcm]表示非限制条件下(limit==0),当前在第pos位模2520余sum且前面各位数字的最小公倍数为lcm的符合条件的数的总数。

    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <cmath>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <cstdlib>
    #include <stack>
    #include <vector>
    #include <set>
    #include <map>
    #define LL long long
    #define mod 100000000
    #define inf 0x3f3f3f3f
    #define eps 1e-6
    #define N 1010
    #define FILL(a,b) (memset(a,b,sizeof(a)))
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define PII pair<int,int>
    using namespace std;
    LL dp[20][2525][50];
    int dig[20],num[2525];
    LL times=0;
    int gcd(int a,int b)
    {
        return a%b==0?b:gcd(b,a%b);
    }
    LL dfs(int pos,int sum,int lcm,int limit)
    {
        if(!pos){//times++;
                return sum%lcm==0;}
        if(!limit&&~dp[pos][sum][num[lcm]])return dp[pos][sum][num[lcm]];
        int len=limit?dig[pos]:9;
        LL ans=0;
        for(int i=0;i<=len;i++)
        {
            int newlcm;
            if(i==0)newlcm=lcm;
            else newlcm=lcm/gcd(i,lcm)*i;
            ans+=dfs(pos-1,(sum*10+i)%2520,newlcm,limit&&len==i);
        }
        if(!limit)dp[pos][sum][num[lcm]]=ans;
        return ans;
    }
    LL solve(LL x)
    {
        int len=0;
        while(x)
        {
            dig[++len]=x%10;
            x/=10;
        }
        return dfs(len,0,1,1);
    }
    int check(LL n)
    {
        LL x=n,flag=1;
        while(x)
        {
            int s=x%10;
            x/=10;
            if(s==0)continue;
            if(n%s)flag=0;
        }
        return flag;
    }
    LL fact(LL x)
    {
        LL res=0;
        for(int i=1;i<=x;i++)
        {
            if(check(i))res++;
        }
        return res;
    }
    void init()
    {
        FILL(dp,-1);
        int cnt=0;
        for(int i=1;i<=2520;i++)
            if(2520%i==0)num[i]=++cnt;
    }
    int main()
    {
        LL n;
        int T;
        init();
        scanf("%d",&T);
        while(T--)
        {
            scanf("%I64d",&n);
            printf("%I64d
    ",solve(n)-1);
          //  printf("%I64d
    ",fact(b)-fact(a-1));
           // printf("%I64d
    ",times);
        }
    }
    View Code
  • 相关阅读:
    jquery判断复选框是否选中
    jquery验证网址格式
    jquery右下角返回顶部
    thinkphp分页格式的完全自定义,直接输入数字go到输入数字页
    textarea出现多余的空格
    html渐隐轮播
    linux 路由 route
    ansible 自动化运维工具
    数据库 group by 后其他列的取值
    linux 磁盘io高排查
  • 原文地址:https://www.cnblogs.com/lienus/p/4288719.html
Copyright © 2020-2023  润新知