「SCOI2014」方伯伯的商场之旅

题目描述

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

现在方伯伯要玩一个游戏,商场会给方伯伯两个整数 \(L,R\)。方伯伯要把位置在 \([L, R]\) 中的每个人的石子都合并成一堆石子。每次操作,他可以选择一个人面前的两堆石子,将其中的一堆中的某些石子移动到另一堆,代价是移动的石子数量\(\times\)移动的距离。商场承诺,方伯伯只要完成任务,就给他一些椰子,代价越小,给他的椰子越多。所以方伯伯很着急,想请你告诉他最少的代价是多少。

\(1≤L≤R≤10^{15}, 2≤K≤20\)。

解题思路 :

首先考虑一下对于某一个数如何求出其合并成一堆的代价,观察发现,最终答案的形态一定可以转化成所有数位都移到某一位

那么问题就转化为找出一个数位,使得其他数位移动到它的总代价最小,可以直接带权中位数求解

但实际上,带权中位数在数位 \(dp\) 的过程中状态不好表示,不妨再多考虑一下子问题解法的由来

考虑一下带权中位数 \(p\) ,其必然满足 \(val_p + \sum_{i=1}^{p-1} val_i \geq \sum_{i=p+1}^{n}\) ,反之同理,也就说,其无论往左移动或者往右移动都不会更优了

我们不妨先假设初始的 \(p = 1\) ,那么就只需要考虑 \(p\) 往右移动到 \(p+1\) 新增的代价了,显然是 \(\sum_{i=1}^{p} val_i - \sum_{i=p+1}^{n} val_i\)

此时如果代价 \(< 0\) 那么说明往右移动会更优,当某一时刻代价 \(\geq 0\) 的时候说明 \(p\) 既不能往右移动也不能往左移动了,此时其是带权中位数

也就是说,我们可以让所有数先移动到 \(1\) ,然后算出每一个 \(p\) 向右移动到 \(p+1\) 的代价,然后把所有 \(<0\) 的代价加上即可

具体实现的话就是一个比较简单的数位 \(dp\) ,考虑分两步计算:

\(f[i][0/1]\) 表示前 \(i\) 个数位,之前是否是上界的前缀的数全部移到第一位的总代价,枚举数位转移即可

对于每一个 \(p\in[1,len]\) ,算出 \(g[i][sum][0/1]\) 表示前 \(i\) 个数位,满足 \(\sum_{i=1}^{p} val_i - \sum_{i=p+1}^{n} val_i = sum\) 的数的个数,也是简单的枚举数位转移即可

注意在前导 \(0\) 的处理上,前导 \(0\) 不能被计算到距离里面,可以考虑每次只做恰好等于 \(n\) 位的数,多拿几个上界做几次,也可以加细节判掉,总复杂度是 \(O(log^3nK)\)

/*program by mangoyang*/
#include<bits/stdc++.h>
#define inf (0x7f7f7f7f)
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
template <class T>
inline void read(T &x){
int f = 0, ch = 0; x = 0;
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
if(f) x = -x;
} #define int ll const int zzd = 401; int f[25][2], ss[25][2], g[25][1005][2], s[25], tmp[25], L, R, bs, lim, ans, ans2; inline int Getcost(){
int res = 0; memset(f, 0, sizeof(f)), memset(ss, 0, sizeof(ss));
f[1][0] = s[1] - 1, f[1][1] = 1;
for(int i = 2; i <= lim; i++){
for(int j = 0; j < bs; j++){
f[i][0] += f[i-1][0];
ss[i][0] += ss[i-1][0] + f[i-1][0] * (i - 1) * j;
}
for(int j = 0; j < s[i]; j++){
f[i][0] += f[i-1][1];
ss[i][0] += ss[i-1][1] + f[i-1][1] * (i - 1) * j;
}
f[i][1] += f[i-1][1];
ss[i][1] += ss[i-1][1] + f[i-1][1] * s[i] * (i - 1);
}
res += ss[lim][0] + ss[lim][1];
return res;
} inline int solve(int num){
lim = 0; while(num) tmp[++lim] = num % bs, num /= bs;
for(int i = 1; i <= lim; i++) s[i] = tmp[lim-i+1];
int cost = Getcost();
for(int p = 1; p <= lim; p++){
memset(g, 0, sizeof(g)), g[1][zzd-s[1]][1] = 1;
for(int i = 1; i < s[1]; i++) g[1][zzd-i][0] = 1;
for(int i = 2; i <= lim; i++)
for(int j = -400; j <= 400; j++){
int sgn = i <= p ? 1 : -1;
for(int k = 0; k < bs; k++) g[i][j+zzd][0] += g[i-1][j+sgn*k+zzd][0];
for(int k = 0; k < s[i]; k++) g[i][j+zzd][0] += g[i-1][j+sgn*k+zzd][1];
g[i][j+zzd][1] += g[i-1][j+sgn*s[i]+zzd][1];
}
for(int j = 1; j <= 400; j++) cost -= (g[lim][j+zzd][0] + g[lim][j+zzd][1]) * j;
}
return cost;
} inline int calc(int x){
int num = x, n = 0, ans = 0;
while(num) ++n, num /= bs;
ans += solve(x); int base = 0;
for(int i = 1; i < n; i++)
base = base * bs + bs - 1, ans += solve(base);
return ans;
} signed main(){
read(L), read(R), read(bs);
cout << calc(R) - calc(L - 1);
return 0;
}

「SCOI2014」方伯伯的商场之旅的更多相关文章

  1. 「SCOI2014」方伯伯的商场之旅 解题报告

    「SCOI2014」方伯伯的商场之旅 我一开始的想法会被两个相同的集合位置去重给搞死,不过应该还是可以写的,讨论起来老麻烦. 可以先钦定在\(1\)号点集合,然后往后调整一部分. 具体一点,通过前缀和 ...

  2. 「SCOI2014」方伯伯运椰子 解题报告

    「SCOI2014」方伯伯运椰子 可以看出是分数规划 然后我们可以看出其实只需要改变1的流量就可以了,因为每次改变要保证流量守恒,必须流成一个环,在正负性确定的情况下,变几次是无所谓的. 然后按照套路 ...

  3. 「SCOI2014」方伯伯的 OJ 解题报告

    「SCOI2014」方伯伯的 OJ 和列队有点像,平衡树点分裂维护即可 但是需要额外用个set之类的对编号查找点的位置 插入完了后记得splay,删除时注意特判好多东西 Code: #include ...

  4. 「SCOI2014」方伯伯的玉米田 解题报告

    #2211. 「SCOI2014」方伯伯的玉米田 发现是取一个最长不下降子序列 我们一定可以把一个区间加的右端点放在取出的子序列的最右边,然后就可以dp了 \(dp_{i,j}\)代表前\(i\)个玉 ...

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. Ubuntu 下 CodeBlocks 修改用户自定义颜色主题 及 更新CodeBlocks到最新版本

    Code::Blocks默认的白色编辑器界面看久了眼睛很累, 所以想换成dark的主题, 眼睛会舒服些. 1. 安装好codeblocks后, 先运行一次, 关闭, 这时程序会提示你是否要保存defa ...

  2. WebStorm 2016激活

    最近在网上找到一个激活webStorm 的好东西.博主说对jetbrains下的所有产品都是可以用这种方式激活的...如:PhpStorm,IntelliJ JDEA等. 但别的产品我没有试过.对于w ...

  3. sublime 直接运行php代码

    只需要简单的配置就可以进行 操作. 首先配置php环境变量 配置完成后打开sublime 点击新编译系统 { "cmd": ["php", "$fil ...

  4. HTML如何编写为桌面程序

    学过/用过HTML的人应该都知道HTML是标记语言,是在网页上执行/使用的,在这里小编告诉你HTML也可以用来做桌面程序,这种桌面程序一般是微客户端 工具/原料   html dreamweaver ...

  5. Minimum Palindromic Factorization(最少回文串分割)

    Minimum Palindromic Factorization(最少回文串分割) 以下内容大部分(可以说除了关于回文树的部分)来自论文A Subquadratic Algorithm for Mi ...

  6. Python os模块和sys模块 操作系统的各种接口

    一.os模块 这个模块提供了一个便携式去使用操作系统的相关功能,如果只是想操作路径,请参阅os.path模块. ''' os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径 ...

  7. 第一天开始使用Oracle

    上半年虽然已经学习了Oracle,但是基本上实验课都没怎么实践过,感觉自己之前过得太水了! 在我的印象里,Oracle 的难度相当于工程师的建设一个亚洲最大的医院一样,也如医生的99%失败率的手术: ...

  8. ZOJ 1610 Count the Colors(区间染色)

    题目大意:多组数据,每组给一个n(1=<n<=8000),下面有n行,每行有l,r,color(1=<color<=8000),表示将l~r颜色变为color,最后求各种颜色( ...

  9. 以太坊go-ethereum项目源码本地环境搭建

    如果要深入了解go-ethereum项目的实现与机制,看源代码是必不可少的.今天这篇博客就简单介绍一下如何在本地搭建项目的开发环境. GO语言环境搭建 以win8为例,访问地址https://gola ...

  10. hive(七)hive-运行方式、GUI接口、权限管理

    1.Hive运行方式: 命令行方式cli:控制台模式 脚本运行方式(实际生产环境中用最多) JDBC方式:hiveserver2 web GUI接口 (hwi.hue等)   1.1Hive在CLI模 ...