• CF55D Beautiful numbers


    题目描述

    对于一个数,如果他能被任何一位上的数整除,那么他就是beautiful number,有t组询问求[l,r]的beautiful number。

    1<=li<=ri<=91018

    题解

    看到没有一点思路,甚至想到上次做的数位DP想把[0,9]都开出一维,但是不仅空间过不去,而且不知道咋处理这个数没出现。

    那么就去借鉴题解,lcm(???)

    整除每一位就是整除出现过的数的lcm!!!

    [1..9]的最小公倍数2520,出现过的数的lcm一定是2520的因数,所以只用判断x%2520是不是lcm的倍数即可,因为%相当于减法,那么-2520就是减多次lcm,就相当于%lcm只是最后的数在[0,2520)之间。

    所以f[s][sum][lcm]表示当前第s位,%2520为sum,出现过的数的lcm

    但是还是空间爆了,但是还是因为lcm是2520的因数,所以第三维只用开因数个数大小即可,同一个数组映射。

    #include<bits/stdc++.h>
    using namespace std;
    
    #define ll long long
    const int mod=2520;
    int t,cnt,mp[2530];
    ll l,r;
    ll f[20][2530][50];
    int len,num[20];
    
    int gcd(int a,int b){
        return !b ? a : gcd(b,a%b);
    }
    
    ll dfs(int s,int sum,int lcm,bool lim){
        if(!s) return !(sum%lcm);
        if(!lim&&f[s][sum][mp[lcm]]!=-1) return f[s][sum][mp[lcm]];
        int mx= lim ? num[s] : 9;
        ll ret=0;
        for(int i=0;i<=mx;i++)
         ret+=dfs(s-1,(sum*10+i)%mod,!i ? lcm : lcm/gcd(lcm,i)*i,lim&&i==mx);
        if(!lim) f[s][sum][mp[lcm]]=ret;
        return ret;
    }
    
    ll cx(ll x){
        len=0;
        while(x){
            num[++len]=x%10;
            x/=10;
        }
        return dfs(len,0,1,true);
    }
    
    int main(){
        for(int i=1;i<=mod;i++)
         if(!(mod%i)) mp[i]=++cnt;
        scanf("%d",&t);
        memset(f,-1,sizeof(f));
        while(t--){
            scanf("%I64d%I64d",&l,&r);
            printf("%I64d
    ",cx(r)-cx(l-1));
        }
    }
    CF55D Beautiful numbers
  • 相关阅读:
    搜索条件中的模式匹配,及包含关键字条件匹配
    Makefile用法,详细到让人吐。
    循序渐进实现仿QQ界面(三):界面调色与控件自绘
    VC 多线程编程
    用UDL快速生成一个数据库连接字符串。
    VC CMarkup所有方法说明
    VC判断控件是否按钮。
    学习笔记(一)
    libvirt0.8.2安装(方法一)
    centos中kvm网桥的设置
  • 原文地址:https://www.cnblogs.com/sto324/p/11402749.html
Copyright © 2020-2023  润新知