题目描述

Blinker 有非常多的仰慕者,他给每个仰慕者一个正整数编号。而且这些编号还隐藏着特殊的意义,即编号的各位数字之积表示这名仰慕者对Blinker的重要度。 现在Blinker想知道编号介于某两个值A,B之间,且重要度为某个定值K的仰慕者编号和。


输入格式

输入的第一行是一个整数N,表示Blinker想知道的信息个数。 
接下来的N行,每行有三个数,A,B,K。表示 Blinker想知道编号介于A和B之间的,
重要度为K的仰慕者的编号和。


输出格式

输出N行,每行输出介于A和B之间,重要度为 K的仰慕者编号和。结果可能很大,
模上20120427。


提示

【数据范围】 
对于20%的数据,保证:  2<=A<=B<=1000000000,1<=N<=30 
对于50%的数据,保证:2<=A<=B<=1000000000000000000,1<=N<=30 
对于100%的数据,保证:  2<=A<=B<=1000000000000000000,1<=N<=5000


  • 题解:

    • 由于因子只有2 3 5 7 , 状态大概有3e4+,不超过4e4;
    • 用HASH_TABLE存下来;
    • 多组询问,先预处理$i$位的答案;
    • 对每组询问$dfs$统计答案,如果没有前导零并且没有抵达上界则直接返回,否则进一步$dfs$
    • 代码不太好些,注释里有关于变量的说明;
    • 注意$K=0$和$K \neq 0$最好分开统计;
    • $n$为位数上界,时间复杂度:$O(T*10n +n*4e4*10)$

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 const int N=20,M=4e4,sz=1234561,mod=20120427;
 5 ll A,B,K;
 6 int cnt,a[N],pw[N];
 7 int o,hd[sz],nt[sz];ll v[sz];
 8 void upd(int&x,int y){x+=y;if(x>=mod)x-=mod;}
 9 void add(ll x){
10     int u=x%sz;
11     for(int i=hd[u];i;i=nt[i])if(v[i]==x)return;
12     nt[++o]=hd[u],hd[u]=o,v[o]=x;
13 }
14 int find(ll x){
15     int u=x%sz;
16     for(int i=hd[u];i;i=nt[i])if(v[i]==x)return i;
17     return 0;
18 }//HASH表
19 void dfs(int x,int y,ll z){
20     if(x==18)add(z);
21     else{
22         if(!y)return;
23         for(int i=x;i<=18;++i){
24             dfs(i,y-1,z);
25             z*=y;
26         }
27     }
28 }//dfs方案
29 namespace Solve{
30     int f[N][M],g[N][M];//f[位数][乘积]
31     void init(){
32         f[0][1]=1;
33         for(int i=0;i<18;++i)
34         for(int j=1;j<=o;++j)
35         if(f[i][j]){
36             for(int l=0;l<=9;++l){
37                 int y=find(v[j]*l);
38                 upd(f[i+1][y],f[i][j]);
39                 upd(g[i+1][y],(g[i][j]*10+f[i][j]*l)%mod);
40             }
41         }
42     }//预处理i位无限制的答案
43     int cal1(int i,int j,int k,ll x,ll y){//已经枚举好的位数,前导零,上界,前i位的值,当前K
44         if(i==cnt)return y==1?x:0;
45         if(!k&&!j)return (1ll*x*pw[cnt-i]%mod*f[cnt-i][find(y)]%mod+g[cnt-i][find(y)])%mod;
46         int re=0,l=j?0:1,r=k?a[i+1]:9;
47         for(int i1=l,t;i1<=r;++i1)if(!i1||y%i1==0){
48             ll y1=!i1?y:y/i1;
49             upd(re, t=cal1(i+1,j&&!i1,k&&i1==a[i+1],(x*10+i1)%mod,y1));
50         }
51         return re;
52     }
53     int cal0(int i,int j,int k,ll x,ll y){//前四个同cal1,y为前i为是否出现0
54         if(i==cnt)return !y?x:0;
55         if(!k&&!j){
56             if(!y)return (1ll*x*pw[cnt-i]%mod*pw[cnt-i]%mod+1ll*(pw[cnt-i]-1)*pw[cnt-i]/2%mod)%mod;//后面cnt-i任意;
57             else return 1ll*x*pw[cnt-i]%mod*f[cnt-i][o]%mod+g[cnt-i][o];//后面cnt-i为乘积为0;
58         }
59         int re=0,l=0,r=k?a[i+1]:9;
60         for(int i1=l;i1<=r;++i1){
61             int y1=j&&!i1?1:y*i1;
62             upd(re, cal0(i+1,j&&!i1,k&&i1==a[i+1],(x*10+i1)%mod,y1));
63         }
64         return re;
65     }
66     //注意理解一下两个方面:
67     //是如何统计前i位达到上界,i+1位不是上界的答案的;(状态k)
68     //是如何统计位数小于上界位数cnt的答案的; (状态j)
69     //上界是如何被统计的(line44)
70 }
71 int main(){
72     #ifndef ONLINE_JUDGE
73     freopen("T2.in","r",stdin);
74     freopen("T2.out","w",stdout);
75     #endif
76     dfs(0,9,1);add(0);
77     Solve::init();
78     for(int i=pw[0]=1;i<=18;++i)pw[i]=pw[i-1]*10%mod;
79     int T;scanf("%d",&T);
80     while(T--){
81         int ans=0;
82         scanf("%lld%lld%lld",&A,&B,&K);A--;
83         cnt=0;while(A)a[++cnt]=A%10,A/=10;
84         for(int i=1;i<=cnt>>1;++i)swap(a[i],a[cnt-i+1]);
85         ans-= K?Solve::cal1(0,1,1,0,K) : Solve::cal0(0,1,1,0,1);
86         cnt=0;while(B)a[++cnt]=B%10,B/=10;
87         for(int i=1;i<=cnt>>1;++i)swap(a[i],a[cnt-i+1]);
88         ans+= K?Solve::cal1(0,1,1,0,K) : Solve::cal0(0,1,1,0,1);
89         printf("%d\n",(ans%mod+mod)%mod);
90     }
91     return 0;
92 }

View Code

转载于:https://www.cnblogs.com/Paul-Guderian/p/10410499.html

bzoj2757【scoi2012】Blinker的仰慕者相关推荐

  1. bzoj2757: [SCOI2012]Blinker的仰慕者

    bzoj2757: [SCOI2012]Blinker的仰慕者 Description Blinker 有非常多的仰慕者,他给每个仰慕者一个正整数编号.而且这些编号还隐藏着特殊的意义,即编号的各位数字 ...

  2. BZOJ2757 : [SCOI2012]Blinker的仰慕者

    BZOJ AC900题纪念~~ 若K>0,则 设f[i][j]表示i位数字,积为j的数字的个数 g[i][j]表示i位数字,积为j的数字的和 DP+Hash预处理 查询时枚举LCP然后统计贡献 ...

  3. SCOI2012 Blinker的仰慕者 BZOJ 2757

    2757: [SCOI2012]Blinker的仰慕者 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 1038 Solved: 291 Descrip ...

  4. 数位dp BZOJ 2757: [SCOI2012]Blinker的仰慕者

    2757: [SCOI2012]Blinker的仰慕者 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 562  Solved: 133 [Submi ...

  5. BZOJ 2757: [SCOI2012]Blinker的仰慕者 数位DP

    好繁琐,因为难处理,分为k==0和k!=0两类处理. 代码很丑...手残伤不起... //#pragma comment(linker, "/STACK:102400000,10240000 ...

  6. [ BZOJ 2757 ]Blinker的仰慕者

    Blinker的仰慕者[L,R] 之间满足各位数字乘积为\(k\) 的数字有多少个.\((L,R \leq 10^{18})\) \(f[i][j][k]:\) 前\(i\)位数,\(j\)代表与上限 ...

  7. 退役前的做题记录2.0

    退役前的做题记录2.0 最近在刷省选题......大致上是按照省份刷的. 不过上面的题目顺序是按照写题的顺序排列的,所以可能会有点乱哈. [BZOJ2823][AHOI2012]信号塔 最小圆覆盖,随 ...

  8. 牛客网dp专题 数位dp

    文章目录 数位dp 例题: NC116652 uva11038 How many 0's NC15035 送分了QAQ NC20669 诡异数字 NC20665 7的意志 NC17385 Beauti ...

  9. 【水】【SCOI】 精简题解

    第二弹 [SCOI2009]生日快乐 搜索.递归划分问题. [SCOI2009]游戏 记忆化搜索.枚举素因子,DP. [SCOI2009]windy数 数位DP,分块统计. [SCOI2009]最长距 ...

最新文章

  1. 皮一皮:中文汉字真是博大精深...
  2. 7开启uasp协议_Dubbo-go 源码笔记(一)Server 端开启服务过程
  3. 手动创建1个基于注解的springmvc项目
  4. Docker常用命令(docker快捷键)海康docker命令 LY
  5. java连续输入_java – 要求用户进行多次输入
  6. 请求的安全信息不可用或无法显示
  7. linux xp镜像文件,让Windows XP镜像文件小一点儿(转)
  8. 判断访问页面的设备并打开对应的网站
  9. Python 基金会 —— 模块和包简介
  10. python计算圆环的面积_基于Python制作美观动态圆环图、饼图
  11. 数据结构考研复试、面试 ——常见提问总结
  12. rgb sw 线主板接口在哪_火力升级 华硕B460重炮手PRO主板豪横上市_搜狐汽车
  13. 调起百度地图客户端之导航功能
  14. 没英语基础怎么自学html5,没有一点英语基础怎么自学
  15. Mirai实现QQ机器人
  16. 计算机RAM ,ROM,NOR FLASH ,NAND FLASH和手机RAM,ROM大家庭血缘关系图
  17. 6个常见的API接口在线管理平台
  18. 笔记十五:研发管理者如何激励他人
  19. 网盘搜索工具整理2020.8
  20. 高龄白菜java学习第109天(java数据结构和算法(27))

热门文章

  1. 是时候聘请首席元宇宙官了吗?
  2. 腾讯云互动直播SDK集成综述
  3. 定位决定地位,眼界决定境界
  4. android hid 音量,android Hid 实现注意事项
  5. 酷睿计算机系统吗,酷睿i3和i5的区别是什么?电脑处理器i3和i5的区别介绍
  6. 【加解密】在线加密工具推荐
  7. 如何成为一位Unity3D游戏开发者:对游戏开发抱有热情
  8. Mathematics for Computer Science 2
  9. 全球与中国高帮滑板鞋市场深度研究分析报告
  10. openSUSE 13.1 Nvidia驱动安装