Description

Conductor is quite a boring profession, as all you have to do is just to sell tickets to the passengers. So no wonder that once upon a time in a faraway galaxy one conductor decided to diversify this occupation. Now this conductor sells several tickets at a time to each passenger. More precisely, he successively gives tickets to the passenger until the sum of the digits on all the tickets given becomes not less than some integer number k. Then this process repeats for the next passenger. Initially conductor has a tape of tickets numbered successively from l to r, inclusive. This way of tickets distribution is quite good, because passengers are glad to get several tickets when they pay only for one. But there is one disadvantage. Since each passenger gets several tickets, it is possible that conductor won't be able to serve all passengers. Your task is to help conductor in this difficult situation. You should calculate how many passengers is the conductor able to serve.

Input

Input file contains three integer numbers lr and k (1 ≤ l ≤ r ≤ 10 18, 1 ≤ k ≤ 1000).

Output

Output should contain exactly one number — the answer to the problem.

Sample Input

  1. sample input
  1. sample output
  1. 40 218 57
  1. 29

【题意】

  有一位售票员给乘客售票。对于每位乘客,他会卖出多张连续的票,直到已卖出的票的编号的数位之和不小于给定的正数 k。然后他会按照相同的规则给下一位乘客售票。初始时,售票员持有的票的编号是从 L 到 R 的连续整数。请你求出,售票员可以售票给多少位乘客。

【分析】

  这题真难想啊,光是理解题解就理解了好久。。

  这题跟前一题是相似的,都是划分区间,但是这题k很小,意味着区间很多,不能一个个区间跑的。这能模拟填数得到答案。模拟填数的话画一个树形图很重要。

  一开始觉得画不画树都没什么关系,但是这题画了树真的好理解很多。因为这一题不能用ans[r]-ans[l],只能DP填l~r之间的数,而且要按从小到大的顺序,所以画树形图就很好看,可以拆成多个子树的并。

  以下图为例,(假设是棵二叉树,好画点,做题的时候实际上是十叉的)。

  

红色路径是L,绿色路径是R。我们填数实际上是从左边的绿色子树一直到右边的蓝色子树。

把原问题分解成多棵子树的子问题在并起来就好了。时间就会很快,是2*logn。

问题就是怎么把子树并起来,一开始会以为不可以,因为后子树的答案和前子树有关。但是我们注意到k很小,不妨记录一下前子树最后一个区间的空间,然后求后子树的答案。

然后这个子树其实是填数过程的后缀那部分的数,我们知道子树的位置所以也知道填数部分的前缀,这个对求子树答案是有影响的,我们子树上的每个数都要加上一个固定的数,所以也把他记录一下。即f[i][j][k]表示高度为i的子树,前子树最后一组剩余空间为j,每个数都要加上k时的答案(我们当作这棵子树的根权值为1,如果不为1而为i则把i加进k里面)。

f[[i][j][k]要记录分了多少组和最后一部分剩余多少,分别记为f[i][j][k].a,f[i][j][k].b

则f[i][j][k]=并(f[i][j][k],f[i-1][f[i][j][k].a][k+l]) (0<=l<=9)

并的话就很容易啦~~~

按顺序求答案就好啦~~

真是太厉害了,其实也不是很难,怎么我想不到,可能是因为之前都是做ans[r]-ans[l]的吧!!

代码如下:

  1. #include<cstdio>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<iostream>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<cmath>
  8. using namespace std;
  9. #define LL long long
  10.  
  11. LL l,r;
  12. int k,st;
  13. int al[],ar[];
  14. int hl[],hr[];
  15.  
  16. void init()
  17. {
  18. for(int i=;i<=;i++)
  19. {
  20. al[i]=(int)l%;l/=;
  21. ar[i]=(int)r%;r/=;
  22. }
  23. for(st=;st>=;st--) if(al[st]!=ar[st]) break;
  24. st++;
  25. hl[]=hr[]=;
  26. for(int i=;i>=;i--)
  27. hl[i]=hl[i+]+al[i],hr[i]=hr[i+]+ar[i];
  28. }
  29.  
  30. struct node
  31. {
  32. LL sm;
  33. int rm;
  34. node ()
  35. {
  36. sm=-;
  37. }
  38. };
  39. node f[][][];
  40. node ans,rm;
  41.  
  42. node get_ans(node x,node y)//combine
  43. {
  44. x.sm+=y.sm;
  45. x.rm=y.rm;
  46. return x;
  47. }
  48.  
  49. node get_f(int x,int y,int z)//x->height y->add z->room
  50. {
  51. if(f[x][y][z].sm!=-) return f[x][y][z];
  52. node now;
  53. if(x==)
  54. {
  55. now.sm=(y+z>=k)?:;
  56. now.rm=(y+z>=k)?:y+z;
  57. }
  58. else
  59. {
  60. now=get_f(x-,y,z);
  61. for(int i=;i<;i++)
  62. {
  63. now=get_ans(now,get_f(x-,y+i,now.rm));
  64. }
  65. }
  66. return now;
  67. }
  68.  
  69. void ffind()
  70. {
  71. ans.sm=(hl[]>=k)?:;ans.rm=(hl[]>=k)?:hl[];
  72. for(int i=;i<st;i++)
  73. {
  74. for(int j=al[i-]+;j<;j++)
  75. {
  76. ans=get_ans(ans,get_f(i-,hl[i]+j,ans.rm));
  77. }
  78. }
  79. for(int i=al[st-]+;i<ar[st-];i++)
  80. {
  81. ans=get_ans(ans,get_f(st-,hl[st]+i,ans.rm));
  82. }int i;
  83. for(i=st-;i>=;i--)
  84. {
  85. for(int j=;j<ar[i-];j++)
  86. {
  87. ans=get_ans(ans,get_f(i-,hr[i]+j,ans.rm));
  88. }
  89. }
  90. if(hr[]+ans.rm>=k) ans.sm++;
  91. printf("%lld\n",ans.sm);
  92. }
  93.  
  94. int main()
  95. {
  96. freopen("a.in","r",stdin);
  97. freopen("a.out","w",stdout);
  98. scanf("%lld%lld%d",&l,&r,&k);
  99. init();
  100. ffind();
  101. return ;
  102. }

[SGU 390]

【其实我没有交,交不了...但是拍了感觉没什么问题..吧


还是放大神题解吧:

【SGU 390】Tickets (数位DP)的更多相关文章

  1. Codeforces Gym 100418J Lucky tickets 数位DP

    Lucky ticketsTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/contest/view ...

  2. SGU 390-Tickets(数位dp)

    题意:有标号l-r的票,要给路人发,当给的票的编号的各数位的总和(可能一个人多张票)不小k时,才开始发给下一个人,求能发多少人. 分析:这个题挺难想的,参考了一下题解,dp[i][sum][left] ...

  3. [DP]数位DP总结

     数位DP总结 By Wine93 2013.7 1.学习链接 [数位DP] Step by Step   http://blog.csdn.net/dslovemz/article/details/ ...

  4. Gym 100418J Lucky tickets(数位dp)

    题意:给定一个n.求区间[1, n]之间的全部的a的个数.a满足: a能整除  把a表示自身二进制以后1的个数 思路:题意非常绕.... 数位dp,对于全部可能的1的个数我们都dfs一次 对于某一个可 ...

  5. SGU_390_Tickets(另类数位DP)

    Tickets Time Limit : 1000/500ms (Java/Other)   Memory Limit : 524288/262144K (Java/Other) Total Subm ...

  6. 【BZOJ1662】[Usaco2006 Nov]Round Numbers 圆环数 数位DP

    [BZOJ1662][Usaco2006 Nov]Round Numbers 圆环数 Description 正如你所知,奶牛们没有手指以至于不能玩"石头剪刀布"来任意地决定例如谁 ...

  7. bzoj1026数位dp

    基础的数位dp 但是ce了一发,(abs难道不是cmath里的吗?改成bits/stdc++.h就过了) #include <bits/stdc++.h> using namespace ...

  8. uva12063数位dp

    辣鸡军训毁我青春!!! 因为在军训,导致很长时间都只能看书yy题目,而不能溜到机房鏼题 于是在猫大的帮助下我发现这道习题是数位dp 然后想起之前讲dp的时候一直在补作业所以没怎么写,然后就试了试 果然 ...

  9. HDU2089 不要62[数位DP]

    不要62 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

随机推荐

  1. JS中==和===的区别

    1.对于string,number等基础类型,==和===是有区别的 1)不同类型间比较,==之比较“转化成同一类型后的值”看“值”是否相等,===如果类型不同,其结果就是不等 2)同类型比较,直接进 ...

  2. Codevs 2776 寻找代表元(二分图匹配)

    2776 寻找代表元 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 黄金 Gold 题目描述 Description 广州二中苏元实验学校一共有n个社团,分别用1到n编号. 广州二 ...

  3. 数位DP入门Ural1057

    CF一战让我觉得很疲倦,所以今天感觉很慢. 昨天解D题时候,因为太累,根本连题目都没看,今天看了之后感觉不会做,听闻是数位DP问题. 有某神说过,DP的功力建立在刷过的题上,我真的毫无功力可言. 介绍 ...

  4. [翻译]ASP.NET Web API 2入门

    原文:Getting Started with ASP.NET Web API 2 Step 1:新建一个Empty的Web API Project. Step 2:添加一个Model: public ...

  5. Spring in action笔记

    耦合的两面性     一方面代码耦合难以测试,会出现打地鼠式的bug特性(修复一个bug,引发另一个bug) 另一方面耦合又是必须的,不同的类必须要进行适当的交互,才能实现功能. bean的四种装配方 ...

  6. 7种基本排序算法的Java实现

    7种基本排序算法的Java实现 转自我的Github 以下为7种基本排序算法的Java实现,以及复杂度和稳定性的相关信息. 以下为代码片段,完整的代码见Sort.java 插入排序 /** * 直接插 ...

  7. linux驱动(一)

    编写模块必须先声明下面两句: #include <linux/module.h>               //这个头文件包含了许多符号与函数的定义,这些符号与函数多与加载模块有关 #i ...

  8. find命令使用, -exec xargs

    find [path]   [expression] 例如:find  /home  -name  \*.o  -exec rm '{}' \; find: 实时精确,支持众多查找标准,遍历指定目录中 ...

  9. HTML实体

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  10. PHP正则表达式 验证电子邮件地址

    我们最经常遇到的验证,就是电子邮件地址验证.网站上常见.各种网页脚本也都常用“正则表达式”(regular expression)对我们输入的电子邮件地址进行验证,判断是否合法.有的还能分解出用户名和 ...