「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. 51nod1110 距离之和最小 V3

    基准时间限制:1 秒 空间限制:131072 KB 分值: 40  X轴上有N个点,每个点除了包括一个位置数据X[i],还包括一个权值W[i].该点到其他点的带权距离 = 实际距离 * 权值.求X轴上 ...

  2. JavaScript计时器

    计时器 基本格式: setInterval(function(){代码},1000): /* 说明:1.setInterval 会返回一个计时器ID值 可以这样接收.var setId = setIn ...

  3. text-align: justify;不能均匀分布问题

    本文地址:http://www.cnblogs.com/veinyin/p/7617610.html  对于text-align来说,一般我们都是使用居中这个属性值,突然今天需要达到这样一个效果: 对 ...

  4. UIDynamicBehavior的行为类翻译

    CHENYILONG Blog UIDynamicBehavior的行为类翻译 © chenyilong. Powered by Postach.io Blog

  5. Shodan 使用

    本文来自:Shodan新手入坑指南, 记录简要用法,以便使用. 文章先给出搜索过滤方法,然后再简单介绍两种使用shodan的方法:使用命令和编写代码. 搜索过滤 hostname:搜索指定的主机或域名 ...

  6. 机器学习-kNN-数据归一化

    一.为什么需要数据归一化 不同数据之间因为单位不同,导致数值差距十分大,容易导致预测结果被某项数据主导,所以需要进行数据的归一化. 解决方案:将所有数据映射到同一尺度 二.最值归一化 normaliz ...

  7. 通过cordova将vue项目打包为webapp

    准备工作:需要之前配置好vue-cli脚架构,安装好cordova环境.下面开始对vue.js项目进行打包,打包环境为Android. 可以看下我的github:https://github.com/ ...

  8. nginx allow 多个ip & ipv4的网段表示方法解析

    参考:https://www.baidu.com/link?url=5aVe_syihQzhHnSDAdLsNNQYqDe_W2GYG1GeIQ130e4mEZbusxQfqGVTdg-dJg8fqM ...

  9. ntp 控制报文

    //make the procedure into block//2014.7.23 OK//#include "CSocket.h" #define NTP_SERVER_IP ...

  10. MYSQL-----流程控制 if() 函数的用法

    语法:IF(condition,result,result) 如果函数的第一个参数中给定的condition符合条件(如,condition不等于0或者不为NULL),那么函数的执行结果为第二个参数中 ...