Beautiful numbers(数位DP+离散化)

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
inputCopy
1
1 9
outputCopy
9
inputCopy
1
12 15
outputCopy
2

题意:求一个区间里面的所有可以被自己每一个位上的非零数整除的数。
思路:DP数组为DP[I][J][K],其中i是表示该数的数位,而j是指该数现在的情况下%2520的大小,因为1~9相乘的和为2520,简化数组,k是表示现在数组要除的数是多少。因为数最大为2520,会超内存,所以离散化数组。

具体代码如下:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <cmath>
using namespace std;
typedef long long ll;
const int maxn = 100010;
const int maxn2= 6010;
const int inf =0x3f3f3f3f;
const int mod = 2520;
ll n,l,r;
ll dp[20][48][2520],b[10];
ll an[200];
int in[mod+10];
int gcd(int a,int b){
    if(b==0) return a;
    else return gcd(b,a%b);
}
int cml(int w,int i){
    w=w/gcd(w,i)*i;
    return w;
}
void init()
{
    int num=0;
    for(int i=1;i<=mod;i++)
        if(mod%i==0)
            in[i]=num++;
}
ll dfs(int pos,int mod1,int mo,int limit){
    if(pos==0) return mo%mod1==0;
    if(!limit&&dp[pos][in[mod1]][mo]!=-1) return dp[pos][in[mod1]][mo];
    int up=limit?an[pos]:9;ll ans=0;
    for(int i=0;i<=up;i++){
        int nmod;
        if(i!=0) nmod=cml(mod1,i);
        else nmod=mod1;
        int nmo=(mo*10+i)%mod;
        ans+=dfs(pos-1,nmod,nmo,limit&&i==an[pos]);
    }
    if(!limit) dp[pos][in[mod1]][mo]=ans;
    return ans;
}
ll c(ll w){
    int cnt=1;
    while(w){
        an[cnt++]=w%10;
        w/=10;
    }
    return dfs(cnt-1,1,0,1);
}
int main()
{
    int t;cin>>t;
    memset(dp,-1,sizeof(dp));
    init();
    while(t--){
        cin>>l>>r;
        memset(b,0,sizeof(b));
        cout<<c(r)-c(l-1)<<endl;
    }
    return 0;
}

发布了35 篇原创文章 · 获赞 25 · 访问量 817

猜你喜欢

转载自blog.csdn.net/qq_43816599/article/details/103898076