• [牛客每日一题](枚举优化,整数分块) NC13221数码


    数码

    题目描述

    给定两个整数 l 和 r ,对于所有满足1 ≤ l ≤ x ≤ r ≤ 10^9 的 x ,把 x 的所有约数全部写下来。对于每个写下来的数,只保留最高位的那个数码。求1~9每个数码出现的次数。

    输入描述:

    一行,两个整数 l 和 r (1 ≤ l ≤ r ≤ 10^9)。

    输出描述:

    输出9行。

    第 i 行,输出数码 i 出现的次数。

    示例1

    输入
    1 4
    输出
    4
    2
    1
    1
    0
    0
    0
    0
    0

    >>> 整除分块(数论分块)证明

    #include <iostream>
    #include <algorithm>
    using namespace  std;
    
    typedef long long LL;
    LL l, r, a[20], b[20];
    
    int GetHead(int x)
    {
        int h = 0 ;
        while (x){
            h = x % 10;
            x /= 10;
        }
        return h;
    }
    void f(LL r, LL *a)
    {
        for (int i = 1; i <= r/i; i++)              //枚举一个因子a
        {
            int b = r/i;                            //b的范围左界是i+1(为了不算重复),右界是r/i
            for (int j = 1; j <= r; j *= 10)        //枚举位数(直接用1后面若干个0,方便后面计算)
            {
                for (int k = 1; k <= 9; k++)        // 枚举首位数
                {
                    int x = max(j*k, i+1);          //x是最高位为k的时候的下界
                    int y = min((j *(k+1)) -1, b);  //y是上界
                    if (y-x>=0) a[k] += y-x+1;      //这个区间存在,算个数
                }
            }
            int h = GetHead(i);             //算a的首位
            a[h] += b-i+1;                  //算用了多少个a
        }
    }
    
    int main()
    {
        scanf("%lld%lld", &l, &r);
        f(r, a);
        f(l - 1, b);
        for(int i = 1; i <= 9; ++i)
            printf("%lld\n", a[i]-b[i]);
        return 0;
    }
    
    
  • 相关阅读:
    华为lab-rs-v1-2.11_OSPF与ISIS互通
    jdk源码分析红黑树——插入篇
    jdk源码分析PriorityQueue
    jdk源码分析ArrayDeque
    jdk链表笔记
    jdk顺序表笔记
    SpringMVC类型转换器、属性编辑器
    SpringMVC基本使用
    spring整合hibernate
    spring aop注解配置
  • 原文地址:https://www.cnblogs.com/Knight02/p/16255360.html
Copyright © 2020-2023  润新知