zoukankan      html  css  js  c++  java
  • A NB群友 【记忆化搜索】(2019年华南理工大学程序设计竞赛(春季赛))

    冲鸭!去刷题:https://ac.nowcoder.com/acm/contest/625/A

    题目描述 

    CC是著名的算法竞赛选手,他不仅人长得帅,而且技术了得,自然而然就有了许多粉丝。

    为了能帮助粉丝们提高竞技水平,CC建立了一个粉丝群,每天CC都会在粉丝群里和群友深入交流黑科技。然而,有些群友老是不努力训练,成天想着复读,比如当CC在群里面发了个整数0,那紧接着就会有群友发整数1,然后又会有群友发整数2……这引起了CC的不满,于是CC决定踢掉一些群友。

    CC的粉丝群人数为无穷大。当CC发出整数0后,其他群友就会跟着轮流发整数1, 2, 3, 4, ...,依此类推。需要注意的是,每个群友都会恰好发一次整数,每个群友发的整数两两不同。CC认为,在不考虑前导零的情况下,如果某个群友发的整数在十进制表示下的各位数字不含0及1,那么这个群友就是NB的,否则就是不NB的。例如,群友A发的整数是3482,该数的各位数字分别为3、4、8、2,其中不含0、1,因此群友A是NB的;另一方面,群友B发的整数402,而该数的十位数字是0,因此群友B是不NB的。

    现在CC决定,踢掉所有不NB的群友。于是经过一番奥妙重重的踢人操作后,粉丝群里只剩下NB群友。然而,CC觉得剩下的这些NB群友还是too naive,因此他打算邀请一些NB群友参加线下训练营(来现场教做人)。具体来说,CC会给出两个正整数L,R,然后他会邀请发出的整数的各位数字之积在区间[L,R]内的NB群友。

    举例来说,假如CC给出的区间为L = 50, R = 300,那么发了567的群友会被邀请线下参赛,因为5×6×7=210;同理,发了255的群友也会被邀请,因为2×5×5=50。但是,发了328的群友则不会收到邀请,因为3×2×8=48∉[50,300]。
     

    输入描述:

    第一行是一个整数T (1≤T≤50),表示数据组数。
    接下来T行,每行两个整数L,R (1LR2321)L,R (1≤L≤R≤232−1),表示一组询问。

    输出描述:

    输出共T行。对于每个询问,输出一行一个整数ans,表示CC邀请参加线下训练营的NB群友人数模109+7109+7的结果。
    示例1

    输入

    复制
    4
    3 6
    4 9
    2147483648 4294967295
    5 5

    输出

    复制
    7
    13
    793516016
    1

    解题思路:

    看到无穷多位,有点蒙。

    不过考虑 R 的范围最大到 2^32 而且每一位不取 0 或者 1,所以位数是有限的,而且不多。

    这道题的正解也正是暴搜。

    暴搜出 sum[ R, 1 ],  sum[ L-1, 1 ], 两者作差。

    搜索过程即枚举每一位的数 d.

    而每位求积的过程有很多状态是重复的,记录一下状态值,减少暴力。

    最后再取模可以过。

    AC code:

    #include <bits/stdc++.h>
    #define INF 0x3f3f3f3f
    #define LL long long
    using namespace std;
    //const LL MAXN = 1<<32;
    const LL mod = 1e9+7;
    //map<int, int>mmp;
    map<LL, LL>mmp;
    LL dfs(LL now)
    {
        if(mmp.count(now)){
            return mmp[now];
        }
        LL res = 0;
        for(LL i = 2; i <= 9; i++){
            if(now >= i){
                res+=dfs(now/i)+1;
    //            res%=mod;
            }
        }
        return mmp[now] = res;
    }
    
    int main()
    {
        LL L, R;
        int T_case;
        scanf("%d", &T_case);
        while(T_case--){
            scanf("%lld %lld", &L, &R);
            LL ans = (dfs(R)-dfs(L-1))%mod;
            printf("%lld
    ", ans);
        }
    
        return 0;
    }
  • 相关阅读:
    Oracle学习笔记:使用replace、regexp_replace实现字符替换、姓名脱敏
    Oracle学习笔记:外连接(+)的用法
    Oracle学习笔记:with as子查询用法
    Oracle学习笔记:a inner join b与from a,b where a.x=b.x的差异
    oracle查看表,索引,视图,存储过程的定义
    oracle查看监听状态
    由sock引起的感想
    xargs
    oracle知识点小结1
    Oracle系统权限列表
  • 原文地址:https://www.cnblogs.com/ymzjj/p/10713187.html
Copyright © 2011-2022 走看看