Codeforces 55D

基本的数位DP,注意记录那些状态可以用最小的空间判断出整除性。

Codeforces 55D
#include <cstdio>

#include <cstring>

using namespace std;



#define D(x) 



const int MAX_DIGIT_NUM = 20;



int f[MAX_DIGIT_NUM];

long long memoize[MAX_DIGIT_NUM][5][7][8][9][1 << 8];

bool contain[10];



int to_digits(long long n)

{

    int ret = 0;

    while (n > 0)

    {

        f[ret++] = n % 10;

        n /= 10;

    }

    return ret;

}



bool check(int r5, int r7, int r8, int r9, int status)

{

    D(printf("%d%d%d%d %d\n", r5, r7, r8, r9, status));

    memset(contain, 0, sizeof(contain));

    int i = 2;

    while (status)

    {

        contain[i++] = status & 1;

        status >>= 1;

    }

    if (contain[2] && r8 % 2)

    {

        return false;

    }

    if (contain[3] && r9 % 3)

    {

        return false;

    }

    if (contain[4] && r8 % 4)

    {

        return false;

    }

    if (contain[5] && r5 % 5)

    {

        return false;

    }

    if (contain[6] && (r8 % 2 || r9 % 3))

    {

        return false;

    }

    if (contain[7] && r7)

    {

        return false;

    }

    if (contain[8] && r8 % 8)

    {

        return false;

    }

    if (contain[9] && r9 % 9)

    {

        return false;

    }

    D(puts("***"));

    return true;

}



long long dfs(int digit, bool less, int r5, int r7, int r8, int r9, int status)

{

    D(printf("%d\n", status));

    if (digit < 0)

    {

        return check(r5, r7, r8, r9, status);

    }

    if (less && memoize[digit][r5][r7][r8][r9][status] != -1)

    {

        return memoize[digit][r5][r7][r8][r9][status];

    }

    int limit = less ? 9 : f[digit];

    long long ret = 0;

    for (int i = 0; i <= limit; i++)

    {

        int next_status = i < 2 ? status : status | (1 << (i - 2));

        ret += dfs(digit - 1, less || i < f[digit], i % 5, (r7 * 10 + i) % 7, (r8 * 10 + i) % 8, (r9 * 10 + i) % 9, next_status);

    }

    if (less) 

    {

        memoize[digit][r5][r7][r8][r9][status] = ret;

    }

    return ret;

}



long long work(long long n)

{

    if (n == 0)

    {

        return 1;

    }

    int len = to_digits(n);

    return dfs(len - 1, false, 0, 0, 0, 0, 0);

}



int main()

{

    int t;

    scanf("%d", &t);

    memset(memoize, -1, sizeof(memoize));

    while (t--)

    {

        long long a, b;

        scanf("%I64d%I64d", &a, &b);

        printf("%I64d\n", work(b) - work(a - 1));

    }

    return 0;

}
View Code

 

你可能感兴趣的:(codeforces)