码迷,mamicode.com
首页 > 其他好文 > 详细

CF55D Beautiful numbers

时间:2019-08-23 22:10:59      阅读:86      评论:0      收藏:0      [点我收藏+]

标签:hid   多次   出现   eof   pen   个数   大小   之间   msu   

题目描述

对于一个数,如果他能被任何一位上的数整除,那么他就是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\n",cx(r)-cx(l-1));
    }
}
CF55D Beautiful numbers

 

CF55D Beautiful numbers

标签:hid   多次   出现   eof   pen   个数   大小   之间   msu   

原文地址:https://www.cnblogs.com/sto324/p/11402749.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!