• 12.2 NOIP 模拟 准考证号


    Description

    ([a,b]) 中有多少个不含 (37)(4) 的数字。

    (1 leq a, space b leq 2 imes 10^9)

    Solution

    很明显的一道数位 (mathrm{dp}) 啊。但是我太菜了,并不会数位 (mathrm{dp})

    再仔细一看:数位 (mathrm{dp}) 的数据范围咋开这么小啊,是不是想让打表水过啊。于是我们有了一个新的思路:打表。

    可以采用分块的思想,以 (10^7) 为一段,把每一段符合条件的数字个数都计算出来。这样一共有 (200) 段。制表代码如下:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int N = 2e9, unit = 5000000;
    int L, R, x, ans, p[23333];
    
    int solve(int l, int r)
    {
        p[0] = 0, ans = 0;
        for(int i = l; i <= r; i++)
        {
            int x = i, len = 0, fl = 1;
            while(x != 0) { p[++len] = x % 10; x /= 10; }
            for(int j = 1; j <= len; j++)
                if(p[j] == 4 || p[j] == 3 && p[j - 1] == 7)
                    fl = 0;
            ans += fl;
        }
        return ans;
    }
    
    int main()
    {
        freopen("dabiao.out", "w", stdout);
        for(int i = 1; i <= 400; i++)
        {
            L = unit * (i - 1) + 1, R = unit * i;
            printf("%d, ", solve(L, R));
        }
        return 0;
    }
    

    大概一两分钟就能跑出来。

    剩下的跟分块一样。扫描打出来的每一段,如果被 ([a,b]) 区间包含就直接统计答案。区间多余的两边暴力统计。时间复杂度大概是 (mathrm{O(200 + 2 imes 8 imes 10^7)}),极限数据在本地跑大概 (1.1s),可以通过。

    Code

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    const int unit = 1e7;
    int biao[233] = {0, 4435929, 4435929, 4435929, 3936807, 1, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 3936807, 1, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 3936807, 1, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 3936807, 1, 4435929, 4435928, 1, 4435929, 4435928, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4435929, 4435929, 4435929, 3936807, 1, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 3936807, 1, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 3936807, 1, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 3936807, 1, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 3936807, 1, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 3936807, 1, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 3936807, 1, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 3936807, 1, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 3936807, 1, 4435929, 4435928, 1, 4435929, 4435928, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4435929, 4435929, 4435929, 3936807, 1, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 3936807, 1, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 3936807, 1, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 3936807, 1, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 4435929, 3936807, 1, 4435929, 4435929, 4435929, 4435929, 4435929};
    int a, b, L, R, res, flg = 0, p[2333], lx = 0x3f3f3f3f, rx = 0, ans = 0;
    
    inline int solve(int l, int r)
    {
        p[0] = 0, res = 0;
        for(int i = l; i <= r; i++)
        {
            int x = i, len = 0, fl = 1;
            while(x != 0) { p[++len] = x % 10; x /= 10; }
            for(int j = 1; j <= len; j++)
                if(p[j] == 4 || p[j] == 3 && p[j - 1] == 7)
                    fl = 0;
            res += fl;
        }
        return res;
    }
    
    int main()
    {
        scanf("%d%d", &a, &b);
        for(int i = 1; i <= 200; i++)
        {
            L = unit * (i - 1) + 1, R = unit * i;
            if(a <= L && b >= R)
            {
                flg = 1;
                lx = min(lx, L);
                rx = max(rx, R);
                ans += biao[i];
            }
            if(L > b) break;
        }
        if(flg && lx > a) ans += solve(a, lx - 1);
        if(flg && rx < b) ans += solve(rx + 1, b);
        if(!flg) ans = solve(a, b);
        printf("%d", ans);
        return 0;
    }
    
  • 相关阅读:
    uboot中fdt命令的使用
    unlocked_ioctl与compat_ioctl
    I2C中关于ACK和NACK的几点东西
    对IIC总线时序的一点理解以及ACK和NACK(NAK)
    usb Defined Class Codes
    排序检索数据
    【转载】5.Linux 网络编程——UDP编程
    【转载】4.Linux 网络编程——套接字的介绍
    【转载】3.Linux 网络编程——网络字节序、地址转换
    【转载】2. Linux 网络编程——网络字节序、地址转换
  • 原文地址:https://www.cnblogs.com/Andy-park/p/14085007.html
Copyright © 2020-2023  润新知