zoukankan      html  css  js  c++  java
  • 杂题集萃[3]

    题目描述

    小N对于数字的大小一直都有两种看法。

    第一种看法是,使用字典序的大小(也就是我们常用的判断数字大小的方法,

    假如比较的数字长度不同,则在较短一个前面补齐前导0,再比较字典序),

    比如(43<355),(10<11)。第二种看法是,对于一个数字(a_ka_{k-1}a_{k-2}...a_0)

    定义他的权值为,也就(a_k×a_{k-1}×a_{k-2}×...×a_0) 是各个数位的乘积。

    现在给定两个区间,[L,R]与[L1,R1]。小N现在想知道,有多少使用字典序

    判大小法在[L,R]之间的数字,满足其第二种定义的权值也在[L1,R1]之间。

    换句话说,对于一个数x,定义f(x)为x的各个数位的乘积。对于L<=x<=R,问有

    多少x满足,L1<=f(x)<=R1。

    输入描述:

    第一行四个整数L,R,L1,R1。

    输出描述:

    一行一个整数,代表小N想知道的数的数量。

    • 输入

    34 10000 24 57 
    
    • 输出

    777
    

    数据范围:

    20%: L,R <= 10000000

    40%: L,R <= 3*10^7

    60%: L,R,L1,R1 <= 10^9

    另外有20%:L1,R1<=1000

    100%: 0<=L,R,L1,R1 <= 10^18, L <= R, L1 <= R1

    题解

    考虑数位DP,注意判定前导零。

    当然也可以用记忆化搜索233。

    code

    • 记忆化搜索
    #include <bits/stdc++.h>
    #define int long long
    using namespace std;
    int l,r,L,R;
    map<int,int>f[30];
    int lim[30];
    inline int dfs(int p,int sum,bool jud){
        // p 从高到低处理到第几位
        // sum 数字的各位的乘积,-1为前导零
        // jud 1为等于 0为小于
        if(!p){
            if(sum==-1) sum=0;
            return (L<=sum&&sum<=R);
        }
        if(!jud&&f[p][sum]) return f[p][sum]-1;
        int tmp=jud?lim[p]:9,ans=0;
        for(int i=0;i<=tmp;++i)
        if(sum==-1){
            if(i==0) ans+=dfs(p-1,-1,jud&&(i==tmp));
            else     ans+=dfs(p-1,i,jud&&(i==tmp));
        }
        else ans+=dfs(p-1,i*sum,jud&&(i==tmp));
        if(!jud)f[p][sum]=ans+1;
        return ans;
    }
    inline int slove(int x){
        if(x==-1) return 0;int p=0;
        while(x) lim[++p]=x%10,x/=10;
        return dfs(p,-1,1);
    }
    signed main(){
        scanf("%lld %lld %lld %lld",&l,&r,&L,&R);
        printf("%lld",slove(r)-slove(l-1));return 0;
    }
    
  • 相关阅读:
    大数据学习笔记01
    寻址方式
    指令格式
    虚拟存储器
    高速缓冲存储器Cache
    双端口RAM和多模块存储器
    主存储器与CPU的连接
    半导体存储器
    存储系统——基本概念
    算术逻辑单元
  • 原文地址:https://www.cnblogs.com/Sparks-Pion/p/9656171.html
Copyright © 2011-2022 走看看