zoukankan      html  css  js  c++  java
  • 数位dp暂退-[ZJOI2010]数字计数

    特殊的计数问题

    这道题不同于之前,之前都是满足****条件的数有多少个,现在是统计某个小数字在所有的数字中出现了几次。

    考虑暴力(以1为例子):
    0->1 2 3 4 5 6 7 8 9
    1->0 1 2 3 4 5 6 7 8 9
    我们只要枚举每一位的每一种可能,然后记录组成的数中1出现了多少次,就可以了。

    然后我们考虑用记忆化来优化:令f[i][j][0/1][0/1] 表示考虑到了第i位,在组起的数中统计的数已经出现了j次,后两位就是数位dp常见的前导零,上界的处理了。

    这样到达同一种状态时就会返回。

    code:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #define int long long 
    using namespace std;
    const int maxn = 15;
    int f[maxn][2][maxn][2];
    int num[maxn];  
    int dfs(int len, bool lmt, int cur, bool zeo, int d)
    {
        int ans = 0;
        if (len == 0) return cur;  
        if (f[len][lmt][cur][zeo] != -1) return f[len][lmt][cur][zeo];  
        for (int i = 0; i < 10; i ++){
            if (!lmt && i > num[len]) break;
            ans += dfs(len-1, lmt || (i<num[len]), cur+((!zeo || i) && (i==d)), zeo && (i == 0), d);
        }
        f[len][lmt][cur][zeo] = ans;
        return ans;
    }
    
    int solve(int x, int d)
    {
        int len = 0;
        while (x){
            num[++ len] = x%10;
            x /= 10;
        } 
        memset(f, -1, sizeof f); 
        return dfs(len, 0, 0, 1, d); 
    }
    signed main()
    {
        int a, b; 
        cin>>a>>b;
        for (int i = 0; i < 10; i ++)
            printf("%lld%c", solve(b, i)-solve(a-1, i), i == 9 ? '
    ' : ' ');
    	return 0;
    }
    

    总结:

    又是一道典型的暴力+优化==正解 的问题,主要是思路不够宽广,应该先打出暴力,然后优化(主要是暴力我打的也不太对qwq,以后诸如此类问题要记录已经组成的数中出现了多少题目要求的数)

  • 相关阅读:
    重写Override和重加载Overload
    Java 继承
    poj 3263 Tallest Cow
    矩阵求和
    全排列
    最大乘积
    三角形面积
    Sum
    搭积木
    调手表
  • 原文地址:https://www.cnblogs.com/bullshit/p/9682218.html
Copyright © 2011-2022 走看看