CodeForces 55D Beautiful numbers (数位dp)

来源:互联网 发布:活体脑细胞结局知乎 编辑:程序博客网 时间:2024/06/11 08:55

D. Beautiful numbers
time limit per test4 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
Volodya is an odd boy and his taste is strange as well. It seems to him that a positive integer number is beautiful if and only if it is divisible by each of its nonzero digits. We will not argue with this and just count the quantity of beautiful numbers in given ranges.

Input
The first line of the input contains the number of cases t (1 ≤ t ≤ 10). Each of the next t lines contains two natural numbers li and ri (1 ≤ li ≤ ri ≤ 9 ·1018).

Please, do not use %lld specificator to read or write 64-bit integers in C++. It is preffered to use cin (also you may use %I64d).

Output
Output should contain t numbers — answers to the queries, one number per line — quantities of beautiful numbers in given intervals (from li to ri, inclusively).

Examples
input
1
1 9
output
9
input
1
12 15
output
2

这题状态不是很好找,
因为这个数能被它每一位整除,,那它一定能被他们的LCM整除,所以可以以它前缀LCM为状态,以及记录其前缀对LCM取膜,这样dp的状态就基本确定了,即dp[pos][LCM][SUM],但是显然LCM的状态有些大,实际根本用不到,所以我们可以将其离散话,在进行计数,具体代码如下:

#include <cstdio>#include <iostream>#include <algorithm>#include <set>#include <map>#include <string>#include <cstring>#include <cmath>using namespace std;#define LL long longconst int mod = 2520;LL dp[19][2520][50][2];int a[100];int index[2530];int gcd(int a,int b){    return b?gcd(b,a%b):a;}int lcm(int a,int b){    return a*b/gcd(a,b);}void init()  //离散化{    int num=0;    for (int i=1;i<=mod;i++){        if (mod%i==0) index[i]=num++;    }}LL dfs(int pos,int sum,int Lcm,int limit){    if (pos==-1){        return (sum%Lcm)==0;    }    if (!limit&&dp[pos][sum][index[Lcm]][limit]!=-1) return dp[pos][sum][index[Lcm]][limit];    int up=limit?a[pos]:9;    LL ans=0;    for (int i=0;i<=up;i++){         int now=Lcm;         if (i) now=lcm(i,Lcm);         ans+=dfs(pos-1,(sum*10+i)%mod,now,limit&&i==a[pos]);    }    if (!limit) dp[pos][sum][index[Lcm]][limit]=ans;    return ans;}LL solve(LL x){    int pos=0;    while (x){        a[pos++]=x%10;        x/=10;    }    return dfs(pos-1,0,1,1);} int main(){    int T;    scanf("%d",&T);    init();    memset(dp,-1,sizeof(dp));    while (T--){        LL l,r;        cin>>l>>r;        LL ans=solve(r)-solve(l-1);        cout<<ans<<endl;    }}
原创粉丝点击