题目链接

先考虑,对于确定的一个数,怎样移动代价最少(或者移到哪个位置最优)?

假设我们都移到下标\(1\)位置(设集合点为\(1\)),那么移动到下标\(2\)与\(1\)相比代价差为:\(下标<1的石子数和-下标>1的石子数和\)。

如果它为负,那么把移到\(1\)的代价加上它,令集合点变为\(2\)...

这样一直改变集合点,直到 \(下标<p的石子数和 \geq 下标>p的石子数和\)。那么移到\(p\)就是最优的。

这样感觉很对。怎么证明?

我们发现式子左边其实就是前缀和,右边是后缀和。因为石子数非负,所以随着\(p\)移动,前缀和是递增的,后缀和递减。

即如果出现 \(前缀和 \geq 后缀和\) 的情况,前缀和就永远大于等于后缀和了。

那么我们对\([l,r]\)的所有数都进行这个贪心。

首先我们要算出所有数集合到1的代价和。这个可以用数位DP算出(递推数的个数,用个数求和)。

然后枚举\(p=2\sim n\)位,我们可以求 以\(p\)为分界,前缀数位和 小于 后缀数位和 且 在\([0,r]\) 的数的个数。其中每个数会减少的代价就是\(前缀和-后缀和\)。

因为数位和最多差不多是230,可以直接枚举这两个状态。同样数位DP。

\(f[i][j][k][0/1]\)表示当前到第\(i\)位,总数位和为\(j\),\(p\)位之前的数位和为\(k\),是否到上界,的数的个数。

另外还可以直接减掉\(k\)那一维。。

记忆化就好写的多了(还快)。

  1. //49592kb 404ms
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <algorithm>
  5. typedef long long LL;
  6. const int N=52,M=245;
  7. int A[N];
  8. LL g[N][2],sum[N][2],f[N][M][M][2];
  9. LL Calc(LL x,int base)
  10. {
  11. int n=0;
  12. for(; x; x/=base) A[++n]=x%base;
  13. std::reverse(A+1,A+1+n);//
  14. memset(g,0,sizeof g), memset(sum,0,sizeof sum);
  15. g[0][1]=1;
  16. for(int i=0; i<n; ++i)//好像还是从0方便。。
  17. {
  18. LL v=g[i][1]; int ai=A[i+1];
  19. g[i+1][1]+=v, sum[i+1][1]=sum[i][1]+v*i*ai;
  20. for(int j=0; j<ai; ++j) g[i+1][0]+=v, sum[i+1][0]+=sum[i][1]+v*i*j;
  21. v=g[i][0];
  22. for(int j=0; j<base; ++j) g[i+1][0]+=v, sum[i+1][0]+=sum[i][0]+v*i*j;
  23. }
  24. LL ans=sum[n][0]+sum[n][1];
  25. for(int p=1; p<n; ++p)
  26. {
  27. f[0][0][0][1]=1;
  28. for(int i=0; i<n; ++i)
  29. {
  30. int ai=A[i+1];
  31. if(i+1<=p)
  32. {
  33. LL v;
  34. for(int j=0,lim=i*(base-1); j<=lim; ++j)
  35. {
  36. if(v=f[i][j][j][1])//好不直观。。
  37. {
  38. f[i+1][j+ai][j+ai][1]+=v;//+=
  39. for(int k=0; k<ai; ++k) f[i+1][j+k][j+k][0]+=v;
  40. }
  41. if(v=f[i][j][j][0])
  42. for(int k=0; k<base; ++k) f[i+1][j+k][j+k][0]+=v;
  43. }
  44. }
  45. else
  46. {
  47. LL v;
  48. for(int j=0,lim=i*(base-1); j<=lim; ++j)
  49. for(int k=0,lim2=p*(base-1); k<=lim2; ++k)
  50. {
  51. if(v=f[i][j][k][1])
  52. {
  53. f[i+1][j+ai][k][1]+=v;
  54. for(int l=0; l<ai; ++l) f[i+1][j+l][k][0]+=v;
  55. }
  56. if(v=f[i][j][k][0])
  57. for(int l=0; l<base; ++l) f[i+1][j+l][k][0]+=v;
  58. }
  59. }
  60. }
  61. for(int i=0,lim=p*(base-1); i<=lim; ++i)//pre
  62. for(int j=i+1,lim2=n*(base-1); i+j<=lim2; ++j)//suf
  63. ans+=(i-j)*(f[n][i+j][i][0]+f[n][i+j][i][1]);
  64. for(int i=1; i<=n; ++i)
  65. for(int j=0,lim=i*(base-1); j<=lim; ++j)
  66. for(int k=0,lim2=p*(base-1); k<=lim2; ++k)
  67. f[i][j][k][0]=0, f[i][j][k][1]=0;
  68. }
  69. return ans;
  70. }
  71. int main()
  72. {
  73. LL L,R; int K; scanf("%lld%lld%d",&L,&R,&K);
  74. printf("%lld\n",Calc(R,K)-Calc(L-1,K));
  75. return 0;
  76. }

BZOJ.3598.[SCOI2014]方伯伯的商场之旅(贪心 数位DP)的更多相关文章

  1. bzoj 3598: [Scoi2014]方伯伯的商场之旅【数位dp】

    参考了这个http://www.cnblogs.com/Artanis/p/3751644.html,好像比一般方法好写 大概思想就是先计算出把所有石子都合并到1位置的代价,这样显然有一些是不优的,然 ...

  2. bzoj 3598 [Scoi2014]方伯伯的商场之旅——数位dp

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3598 TJ:https://www.cnblogs.com/Zinn/p/9351218.h ...

  3. BZOJ3598 SCOI2014方伯伯的商场之旅(数位dp)

    看到数据范围就可以猜到数位dp了.显然对于一个数最后移到的位置应该是其中位数.于是考虑枚举移到的位置,那么设其左边和为l,左右边和为r,该位置数为p,则需要满足l+p>=r且r+p>=l. ...

  4. 洛谷P3286 [SCOI2014]方伯伯的商场之旅

    题目:洛谷P3286 [SCOI2014]方伯伯的商场之旅 思路 数位DP dalao说这是数位dp水题,果然是我太菜了... 自己是不可能想出来的.这道题在讲课时作为例题,大概听懂了思路,简单复述一 ...

  5. [BZOJ3598][SCOI2014]方伯伯的商场之旅(数位DP,记忆化搜索)

    3598: [Scoi2014]方伯伯的商场之旅 Time Limit: 30 Sec  Memory Limit: 64 MBSubmit: 449  Solved: 254[Submit][Sta ...

  6. 【bzoj3598】: [Scoi2014]方伯伯的商场之旅

    Description 方伯伯有一天去参加一个商场举办的游戏.商场派了一些工作人员排成一行.每个人面前有几堆石子.说来也巧,位置在 i 的人面前的第 j 堆的石子的数量,刚好是 i 写成 K 进制后的 ...

  7. [SCOI2014]方伯伯的商场之旅

    Description 方伯伯有一天去参加一个商场举办的游戏.商场派了一些工作人员排成一行.每个人面前有几堆石子.说来也巧,位置在 i 的人面前的第 j 堆的石子的数量,刚好是 i 写成 K 进制后的 ...

  8. 【数位DP】SCOI2014 方伯伯的商场之旅

    题目内容 方伯伯有一天去参加一个商场举办的游戏.商场派了一些工作人员排成一行.每个人面前有几堆石子. 说来也巧,位置在 \(i\) 的人面前的第 \(j\) 堆的石子的数量,刚好是 \(i\) 写成 ...

  9. 【bzoj3598】 Scoi2014—方伯伯的商场之旅

    http://www.lydsy.com/JudgeOnline/problem.php?id=3598 (题目链接) 题意 Solution 原来这就是极水的数位dp,呵呵= =,感觉白学了.htt ...

随机推荐

  1. How to Repair GRUB2 When Ubuntu Won’t Boot

    Ubuntu and many other Linux distributions use the GRUB2 boot loader. If GRUB2 breaks—for example, if ...

  2. Html5 序列帧动画

    <!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> ...

  3. 【可视化】DataV接入ECharts图表库 可视化利器强强联手

    DataV接入ECharts图表库 可视化利器强强联手 摘要: 两个扛把子级产品的结合,而且文末有彩蛋. DataV 数据可视化是搭建每年天猫双十一作战大屏的幕后功臣,ECharts 是广受数据可视化 ...

  4. 在listView中的模糊查询和删除

  5. Java 开发环境配置--eclipse工具进行java开发

    Java 开发环境配置 在本章节中我们将为大家介绍如何搭建Java开发环境. Windows 上安装开发环境 Linux 上安装开发环境 安装 Eclipse 运行 Java Cloud Studio ...

  6. VS2013 "当前不会命中断点.还没有为该文档家在任何符号" 解决办法

    参考:http://blog.csdn.net/u010797208/article/details/40452797 亲测可行

  7. Spark的HA部署

    一.安装JDK.Scala 二.安装zookeeper 三.安装Hadoop 四.安装Spark 1.修改spark/conf/spark-env.sh export JAVA_HOME=/usr/j ...

  8. php中静态方法和静态属性的介绍

    静态分为两个部分:静态属性和静态方法 静态的东西都是给类用的(包括类常量),非静态的都是给对象用的 静态属性 在定义属性的时候,使用关键字static修饰的属性称之为静态属性. 静态方法 使用stat ...

  9. php中常用的正则表达式函数

    php中常用的正则表达式函数 * preg_match() * preg_match_all() * preg_replace() * preg_filter() * preg_grep() * pr ...

  10. django----用户认证(auth模块)

    用法 from django.contrib import auth user = authenticate(username='someone',password='somepassword') l ...