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

Codeforces Beta Round #51---D. Beautiful numbers(数位dp, 巧妙)

时间:2015-02-23 23:41:09      阅读:314      评论:0      收藏:0      [点我收藏+]

标签:dp

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

这题做法真的很精妙
如果一个数可以被它每一位上的数整除,那一定可以被那些数的LCM整除,最大的LCM是2520,因此那些数一定能被2520的因子某个整除
设dp[cur][rest][lcm]表示到第cur位,前面的数组成的数对2520取模为rest,之前的数的lcm为lcm的数的个数,直接这样会超内存,所以第三维离散化一下

前面的数组成的数对2520取模后为什么对答案没有影响呢?
设这个数为2520 * k + b,对lcm取模,lcm是2520的一个因子,因此:
(2520 * k + b) % lcm = b % lcm
所以不影响

然后就是数位dp的事情了
显然要用64位整数

/*************************************************************************
    > File Name: cf55d.cpp
    > Author: ALex
    > Mail: zchao1995@gmail.com 
    > Created Time: 2015年02月23日 星期一 22时25分40秒
 ************************************************************************/

#include <map>
#include <set>
#include <queue>
#include <stack>
#include <vector>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const double eps = 1e-15;
typedef long long LL;
typedef pair <int, int> PLL;

LL dp[33][2600][60];
int LCM_ARR[60];
int HASH[3000];
int cnt;
int bit[30];

LL gcd (LL a, LL b)
{
    return b ? gcd (b, a % b) : a;
}

LL LCM (LL a, LL b)
{
    return a / gcd (a, b) * b;
}

LL dfs (int cur, int rest, int ind, bool flag, bool zero)
{
    if (cur == -1)
    {
        if (zero)
        {
            return 0;
        }
        return (rest % LCM_ARR[ind] == 0);
    }
    if (!flag && ~dp[cur][rest][ind])
    {
        return dp[cur][rest][ind];
    }
    LL ans = 0;
    int end = flag ? bit[cur] : 9;
    for (int i = 0; i <= end; ++i)
    {
        if (zero && !i)
        {
            ans += dfs (cur - 1, 0, 0, flag && (i == end), 1);
        }
        else if (zero && i)
        {
            ans += dfs (cur - 1, i, HASH[i], flag && (i == end), 0);
        }
        else
        {
            if (i == 0)
            {
                ans += dfs (cur - 1, rest * 10 % 2520, ind, flag && (i == end), zero && (i == 0));
                continue;
            }
            int lcm = LCM (LCM_ARR[ind], i);
            ans += dfs (cur - 1, (rest * 10 + i) % 2520, HASH[lcm], flag && (i == end), zero && (i == 0));
        }
    }
    if (!flag)
    {
        dp[cur][rest][ind] = ans;
    }
    return ans;
}

LL calc (LL n)
{
    int ret = 0;
    while (n)
    {
        bit[ret++] = n % 10;
        n /= 10;
    }
    return dfs (ret - 1, 0, 1, 1, 1);
}

int main ()
{
    cnt = 0;
    memset (dp, -1, sizeof(dp));
    for (int i = 1; i <= 2520; ++i)
    {
        if (2520 % i == 0)
        {
            LCM_ARR[++cnt] = i;
            HASH[i] = cnt;
        }
    }
    LL l, r;
    int t;
    scanf("%d", &t);
    while (t--)
    {
        cin >> l >> r;
        cout << calc (r) - calc (l - 1) << endl;
    }
    return 0;
}

Codeforces Beta Round #51---D. Beautiful numbers(数位dp, 巧妙)

标签:dp

原文地址:http://blog.csdn.net/guard_mine/article/details/43919747

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