xgc_woker的博客

“人的生命的价值不在于长短,而在于对社会的贡献。”

BZOJ3679: 数字之积 数位DP

Description
一个数x各个数位上的数之积记为f(x) <不含前导零>
求[L,R)中满足0 < f(x) <= n的数的个数


Sample Input
5
19 22


Sample Output
1


突然发现自己没写过数位DP的blog,写一篇!!!
首先我们发现直接开数组n太大会爆炸。。。
然后我们发现其实1~9的质因数是有限的:2、3、5、7
那你开一个五维数组f[i][x2][x3][x5][x7]表示到第i位,有x2个2,x3个3,x5个5,x7个7。
然后就数位DP乱搞。。。


#include <cstdio>
#include <cstring>

using namespace std;
typedef long long LL;

LL f[20][31][21][13][12];
int n, a[20], len;
int k2, k3, k5, k7;

LL dfs(int x, int x2, int x3, int x5, int x7, bool pd, bool limit) {
    LL oo = 1;
    for(int i = 1; i <= x2; i++) oo *= 2;
    for(int i = 1; i <= x3; i++) oo *= 3;
    for(int i = 1; i <= x5; i++) oo *= 5;
    for(int i = 1; i <= x7; i++) oo *= 7;
    if(oo > n) return 0;
    if(x == 0) {
        if(oo <= n && !pd) return 1;
        else return 0;
    }
    if(f[x][x2][x3][x5][x7] != -1 && !limit && !pd) return f[x][x2][x3][x5][x7];
    int up = 9; LL ans = 0; if(limit) up = a[x];
    if(pd) ans += dfs(x - 1, x2, x3, x5, x7, 1, limit);
    for(int i = 1; i <= up; i++) {
        bool uu = 0;
        if(limit == 1 && i == up) uu = 1;
        int y2 = x2, y3 = x3, y5 = x5, y7 = x7;
        if(i == 2) y2++; if(i == 3) y3++; if(i == 4) y2 += 2; if(i == 5) y5++; if(i == 6) y2++, y3++;
        if(i == 7) y7++; if(i == 8) y2 += 3; if(i == 9) y3 += 2;
        ans += dfs(x - 1, y2, y3, y5, y7, 0, uu);
    }
    if(!limit && !pd) f[x][x2][x3][x5][x7] = ans;
    return ans;
}

LL solve(LL x) {
    if(x == 0) return 0;
    len = 0;
    while(x) a[++len] = x % 10, x /= 10;
    LL ans = 0;
    memset(f, -1, sizeof(f));
    for(int i = 0; i <= a[len]; i++) {
        bool h1 = 0, h2 = 0;
        if(i == 0) h1 = 1; if(i == a[len]) h2 = 1;
        int y2 = 0, y3 = 0, y5 = 0, y7 = 0;
        if(i == 2) y2++; if(i == 3) y3++; if(i == 4) y2 += 2; if(i == 5) y5++; if(i == 6) y2++, y3++;
        if(i == 7) y7++; if(i == 8) y2 += 3; if(i == 9) y3 += 2;
        ans += dfs(len - 1, y2, y3, y5, y7, h1, h2);
    }
    return ans;
}

int main() {
    scanf("%d", &n);
    LL x, y; scanf("%lld%lld", &x, &y);
    printf("%lld\n", solve(y - 1) - solve(x - 1));
    return 0;
}
阅读更多
版权声明:xgc原创文章,未经允许不得转载。 https://blog.csdn.net/xgc_woker/article/details/79965138
文章标签: 数位DP
个人分类: 数位dp
上一篇[Jsoi2015]字符串树 hash+主席树+LCA
下一篇[Scoi2015]情报传递 主席树
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭