zoukankan      html  css  js  c++  java
  • Codeforces Beta Round #51 D. Beautiful numbers

    http://codeforces.com/contest/55/problem/D

    题意:

    询问[l,r]内有多少个数字,满足能被自己的每一位非0数整除

    数位DP

    表示出当前对2520取模的余数,以及目前各个数位数字的最小公倍数

    因为0—9的最小公倍数是2520,而且最小公倍数只有48种情况

        #include<cstdio>
        #include<cstring>
        #include<iostream>
        #include<algorithm>
         
        using namespace std;
         
        typedef long long LL;
         
        const int mod=2520;
         
        int num[21];
        int lcm[11][2525],li[2525],il[51],sl;
        LL dp[21][2525][51];
         
        LL dfs(int dep,bool lim,int r,int lc)
        {    
            if(!lim && dp[dep][r][li[lc]]!=-1) return dp[dep][r][li[lc]];
            if(!dep) return !(r%lc);
            bool nlim;
            int nr,nlcm;
            LL sum=0;
            int up=lim ? num[dep] : 9;
            for(int i=0;i<=up;++i)
            {
                nlim=(lim && i==num[dep]);
                nr=(r*10+i)%mod;
                nlcm=lcm[i][lc];
                sum+=dfs(dep-1,nlim,nr,nlcm);
            }
            if(!lim) dp[dep][r][li[lc]]=sum;
            return sum;
        }
         
        LL solve(LL n)
        {
            int m=0;
            while(n) num[++m]=n%10,n/=10;
            return dfs(m,1,0,1);
        }
         
        void pre()
        {
            for(int i=0;i<=9;++i)
                for(int j=1;j<=mod;++j)
                {
                    if(!i) lcm[i][j]=j; 
                    else lcm[i][j]=i*j/__gcd(i,j);
                }
            sl=0;
            int t;
            for(int i=0,t2=1;i<=3;++i,t2*=2)
                for(int j=0,t3=1;j<=2;++j,t3*=3)
                    for(int k=0,t5=1;k<=1;++k,t5*=5)
                         for(int l=0,t7=1;l<=1;++l,t7*=7)
                         {
                             t=t2*t3*t5*t7;
                            li[t]=++sl;
                            il[sl]=t;
                        }
        }
         
        int main()
        {
            memset(dp,-1,sizeof(dp));
            int T;
            LL l,r;
            pre();
            scanf("%d",&T);
            while(T--)
            {
                cin>>l>>r;
                cout<<solve(r)-solve(l-1)<<'
    ';
            }
        }
  • 相关阅读:
    javaweb登录验证码的实现
    jQuery Ajax 简单的实现跨域请求
    Java Socket长连接示例代码
    Java socket长连接代码实现
    带日期的bean转为json(bean->JSON)
    函数迭代器、生成器、递归
    闭包函数和装饰器
    函数名称空间与作用域
    函数基础
    基本的文件操作
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/14031348.html
Copyright © 2011-2022 走看看