Codeforces #55D-Beautiful numbers (数位dp)

D. Beautiful numbers
time limit per test
4 seconds
memory limit per test
256 megabytes
input
standard input
output
standard 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).

Sample test(s)
input
1
1 9
output
9
input
1
12 15
output
2 

Question link: http://codeforces.com/problemset/problem/55/D

question is
to find the number B in the interval [l,r]: the number is divisible by each of its digits.

If the analysis
is divisible by each digit, it is divisible by the lcm (least common multiple) of the digits in all digits. And the lcm of 1 to 9 is 2520, so we can perform digit dp. When dp[i][j][k] represents the i-th digit,
the number is j, and the lcm of each previous digit is k. But obviously, the value j cannot be directly represented, and we have to find a way to optimize it. Because the essence of recursion to the end is to find x%lcm, then we can think of a property:
x%m==x%(km)%m, in this way, x%lcm==x%2520%lcm, so the second dimension is reduced to within 2520. Now the space complexity is 20*2520*2520, which is still an explosion. Think about where to optimize?
Suddenly found that there are not so many real LCMs, only 48. At this point, the space complexity has become 20*2520*50, and the next step is to solve the recursive memorization, pay attention to the boundary conditions.
See code for details
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
#include<bitset>
#include<map>
#include<deque>
#include<stack>
using namespace std;
typedef pair<int,int> pii;
#define X first
#define Y second
#define pb push_back
#define mp make_pair
typedef long long ll;
#define ms(a,b) memset(a,b,sizeof(a))
const int inf = 0x3f3f3f3f;
const int maxn = 1e5+5;
const int mod = 1e9+7;
const int mm = 2520;
#define lson l,m,2*rt
#define rson m+1,r,2*rt+1
ll dp[20][2550][50];
int has[2550];
int bit[20];
ll gcd(ll a,ll b){
    return (b==0)?a:gcd(b,a%b);
}
ll lcm(ll a,ll b){
    return a/gcd(a,b)*b;
}
void init(){
    int tot=0;
    for(int i=1;i<2550;i++){
        if(mm%i==0){
            has [i] = all ++ ;
        }
    }
}

ll dfs( int pos, int preSum, int preLcm, bool limit){
     if (pos< 0 ) return preSum%preLcm== 0 ; // to the last digit 
    if (!limit && dp[pos][preSum][has [preLcm]]!=- 1 )
         return dp[pos][preSum][has[preLcm]]; // memoization 
    ll ans= 0 ;
     int ed = limit?bit[pos]: 9 ; // this bit has bounds 
    for ( int i= 0 ;i<=ed;i++ ){
         int nowSum = (preSum*10+i)%mm;
        int nowLcm = preLcm;
        if(i) nowLcm = lcm(nowLcm,i);
        ans += dfs(pos-1,nowSum,nowLcm,limit && i==ed);
    }
    if(!limit) dp[pos][preSum][has[preLcm]]=ans;
    return ans;
}
ll solve(ll x){
    int tot=0;
    while(x){
        bit [all ++] = x% 10 ;
        x/=10;
    }
    return dfs(tot-1,0,1,1);
}

int main(){
#ifdef LOCAL
    freopen("in.txt","r",stdin);
#endif // LOCAL
    int t;
    ll l,r;
    ms(dp,-1);
    init();
    scanf("%d",&t);
    while(t--){
        cin>>l>>r;
        cout<<solve(r)-solve(l-1)<<endl;
    }
    return 0;
}

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325050209&siteId=291194637