「SCOI2014」方伯伯的商场之旅
「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」方伯伯的商场之旅的更多相关文章
- 「SCOI2014」方伯伯的商场之旅 解题报告
「SCOI2014」方伯伯的商场之旅 我一开始的想法会被两个相同的集合位置去重给搞死,不过应该还是可以写的,讨论起来老麻烦. 可以先钦定在\(1\)号点集合,然后往后调整一部分. 具体一点,通过前缀和 ...
- 「SCOI2014」方伯伯运椰子 解题报告
「SCOI2014」方伯伯运椰子 可以看出是分数规划 然后我们可以看出其实只需要改变1的流量就可以了,因为每次改变要保证流量守恒,必须流成一个环,在正负性确定的情况下,变几次是无所谓的. 然后按照套路 ...
- 「SCOI2014」方伯伯的 OJ 解题报告
「SCOI2014」方伯伯的 OJ 和列队有点像,平衡树点分裂维护即可 但是需要额外用个set之类的对编号查找点的位置 插入完了后记得splay,删除时注意特判好多东西 Code: #include ...
- 「SCOI2014」方伯伯的玉米田 解题报告
#2211. 「SCOI2014」方伯伯的玉米田 发现是取一个最长不下降子序列 我们一定可以把一个区间加的右端点放在取出的子序列的最右边,然后就可以dp了 \(dp_{i,j}\)代表前\(i\)个玉 ...
- [BZOJ3598][SCOI2014]方伯伯的商场之旅(数位DP,记忆化搜索)
3598: [Scoi2014]方伯伯的商场之旅 Time Limit: 30 Sec Memory Limit: 64 MBSubmit: 449 Solved: 254[Submit][Sta ...
- 洛谷P3286 [SCOI2014]方伯伯的商场之旅
题目:洛谷P3286 [SCOI2014]方伯伯的商场之旅 思路 数位DP dalao说这是数位dp水题,果然是我太菜了... 自己是不可能想出来的.这道题在讲课时作为例题,大概听懂了思路,简单复述一 ...
- 【bzoj3598】: [Scoi2014]方伯伯的商场之旅
Description 方伯伯有一天去参加一个商场举办的游戏.商场派了一些工作人员排成一行.每个人面前有几堆石子.说来也巧,位置在 i 的人面前的第 j 堆的石子的数量,刚好是 i 写成 K 进制后的 ...
- [SCOI2014]方伯伯的商场之旅
Description 方伯伯有一天去参加一个商场举办的游戏.商场派了一些工作人员排成一行.每个人面前有几堆石子.说来也巧,位置在 i 的人面前的第 j 堆的石子的数量,刚好是 i 写成 K 进制后的 ...
- 【数位DP】SCOI2014 方伯伯的商场之旅
题目内容 方伯伯有一天去参加一个商场举办的游戏.商场派了一些工作人员排成一行.每个人面前有几堆石子. 说来也巧,位置在 \(i\) 的人面前的第 \(j\) 堆的石子的数量,刚好是 \(i\) 写成 ...
随机推荐
- Ubuntu 下 CodeBlocks 修改用户自定义颜色主题 及 更新CodeBlocks到最新版本
Code::Blocks默认的白色编辑器界面看久了眼睛很累, 所以想换成dark的主题, 眼睛会舒服些. 1. 安装好codeblocks后, 先运行一次, 关闭, 这时程序会提示你是否要保存defa ...
- WebStorm 2016激活
最近在网上找到一个激活webStorm 的好东西.博主说对jetbrains下的所有产品都是可以用这种方式激活的...如:PhpStorm,IntelliJ JDEA等. 但别的产品我没有试过.对于w ...
- sublime 直接运行php代码
只需要简单的配置就可以进行 操作. 首先配置php环境变量 配置完成后打开sublime 点击新编译系统 { "cmd": ["php", "$fil ...
- HTML如何编写为桌面程序
学过/用过HTML的人应该都知道HTML是标记语言,是在网页上执行/使用的,在这里小编告诉你HTML也可以用来做桌面程序,这种桌面程序一般是微客户端 工具/原料 html dreamweaver ...
- Minimum Palindromic Factorization(最少回文串分割)
Minimum Palindromic Factorization(最少回文串分割) 以下内容大部分(可以说除了关于回文树的部分)来自论文A Subquadratic Algorithm for Mi ...
- Python os模块和sys模块 操作系统的各种接口
一.os模块 这个模块提供了一个便携式去使用操作系统的相关功能,如果只是想操作路径,请参阅os.path模块. ''' os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径 ...
- 第一天开始使用Oracle
上半年虽然已经学习了Oracle,但是基本上实验课都没怎么实践过,感觉自己之前过得太水了! 在我的印象里,Oracle 的难度相当于工程师的建设一个亚洲最大的医院一样,也如医生的99%失败率的手术: ...
- ZOJ 1610 Count the Colors(区间染色)
题目大意:多组数据,每组给一个n(1=<n<=8000),下面有n行,每行有l,r,color(1=<color<=8000),表示将l~r颜色变为color,最后求各种颜色( ...
- 以太坊go-ethereum项目源码本地环境搭建
如果要深入了解go-ethereum项目的实现与机制,看源代码是必不可少的.今天这篇博客就简单介绍一下如何在本地搭建项目的开发环境. GO语言环境搭建 以win8为例,访问地址https://gola ...
- hive(七)hive-运行方式、GUI接口、权限管理
1.Hive运行方式: 命令行方式cli:控制台模式 脚本运行方式(实际生产环境中用最多) JDBC方式:hiveserver2 web GUI接口 (hwi.hue等) 1.1Hive在CLI模 ...