Description

方伯伯有一天去参加一个商场举办的游戏。商场派了一些工作人员排成一行。每个人面前有几堆石子。说来也巧,位置在 i 的人面前的第 j 堆的石子的数量,刚好是 i 写成 K 进制后的第 j 位。
现在方伯伯要玩一个游戏,商场会给方伯伯两个整数 L,R。方伯伯要把位置在 [L, R] 中的每个人的石子都合并成一堆石子。每次操作,他可以选择一个人面前的两堆石子,将其中的一堆中的某些石子移动到另一堆,代价是移动的石子数量 * 移动的距离。商场承诺,方伯伯只要完成任务,就给他一些椰子,代价越小,给他的椰子越多。所以方伯伯很着急,想请你告诉他最少的代价是多少。
例如:10 进制下的位置在 12312 的人,合并石子的最少代价为:
1 * 2 + 2 * 1 + 3 * 0 + 1 * 1 + 2 * 2 = 9
即把所有的石子都合并在第三堆

Input

输入仅有 1 行,包含 3 个用空格分隔的整数 L,R,K,表示商场给方伯伯的 2 个整数,以及进制数

HINT

1 < =  L < =  R < =  10^15, 2 < =  K < =  20

Solution

说白了,这个题就是给了L~R的数,每个数的每个数位是一堆石子,把这堆石子合成一个位置,求总的最小代价。

法一:GZZ法

发现,对于一个数字P,假设钦定最终合并位置是p,

调整的时候,p向左移动一位,代价变化是p及右边所有的数位和-p左边所有数位和。

p向右移动一位,代价变化是p及左边所有数位和-p右边所有数位和。

设最优的位置的数字是x,位置是p,p左边数位和是a,右边是b

那么,一定有不等式:x+a-b>=0 ; x+b-a>=0 就是说,x不论往左往右移动,代价的变化总是增大的。

即:-x<=a-b<=x

所以,如果知道最终填的a-b,和x,p,就可以判断这个p位置填x是不是左边a,右边b的最优解了。

枚举p,x;

伪代码:(cnt是最高位,进制用m,填数用k)

for(p=1~cnt)

for(x=0~m-1)

for(i=cnt~1)

   for(a-b=-200~+200)

  设f[i][a-b][0/1]表示,填完第i位,a-b的值,有没有限制情况下,所有符合情况的数移动到p位置所花费的代价。

g[i][a-b][0/1]表示,f的方案数,即满足情况的数的个数,方便转移。

if(i==p){

    

    continue;

  }

for(k=0;k<m;k++){

    if(i<p)

    else

  }

 在i循环完之后,

 for(a-b=-200~+200)

if(-x<=a-b<x) ret+=f[1][a-b][0/1]

 注意这里是<=和<,因为可能一个数字有两个位置都是最优的合并位置,只能算一遍。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=;
const int M=;
const int fix=;
const int up=;
ll f[N][][];
ll g[N][][];
ll L,R;
int m;
ll ansl,ansr;
int a[N],cnt;
ll wrk(){
ll ret=;
for(int p=;p<=cnt;p++){
for(int x=;x<m;x++){
memset(f,,sizeof f);
memset(g,,sizeof g);
g[cnt+][fix][]=;
for(int i=cnt;i>=;i--){
for(int j=;j<=up;j++){
if(i==p){
if(x<a[i]){
if(g[i+][j][]) g[i][j][]+=g[i+][j][],f[i][j][]+=f[i+][j][];
if(g[i+][j][]) g[i][j][]+=g[i+][j][],f[i][j][]+=f[i+][j][];
}
else if(x==a[i]){
g[i][j][]+=g[i+][j][],f[i][j][]+=f[i+][j][];
g[i][j][]+=g[i+][j][],f[i][j][]+=f[i+][j][];
}
else{
g[i][j][]+=g[i+][j][],f[i][j][]+=f[i+][j][];
}
continue;
} for(int k=;k<m;k++){
if(i>p){//before
if(j+k>up) continue; if(k<a[i]){
g[i][j+k][]+=g[i+][j][],f[i][j+k][]+=f[i+][j][]+(i-p)*k*g[i+][j][];
g[i][j+k][]+=g[i+][j][],f[i][j+k][]+=f[i+][j][]+(i-p)*k*g[i+][j][];
}
else if(k==a[i]){
g[i][j+k][]+=g[i+][j][],f[i][j+k][]+=f[i+][j][]+(i-p)*k*g[i+][j][];
g[i][j+k][]+=g[i+][j][],f[i][j+k][]+=f[i+][j][]+(i-p)*k*g[i+][j][];
}
else{
g[i][j+k][]+=g[i+][j][],f[i][j+k][]+=f[i+][j][]+(i-p)*k*g[i+][j][];
}
}
else{//after
if(j-k<) continue; if(k<a[i]){
f[i][j-k][]+=f[i+][j][]+g[i+][j][]*(p-i)*k,g[i][j-k][]+=g[i+][j][];
f[i][j-k][]+=f[i+][j][]+g[i+][j][]*(p-i)*k,g[i][j-k][]+=g[i+][j][];
}
else if(k==a[i]){
f[i][j-k][]+=f[i+][j][]+g[i+][j][]*(p-i)*k,g[i][j-k][]+=g[i+][j][];
f[i][j-k][]+=f[i+][j][]+g[i+][j][]*(p-i)*k,g[i][j-k][]+=g[i+][j][];
}
else{
f[i][j-k][]+=f[i+][j][]+g[i+][j][]*(p-i)*k,g[i][j-k][]+=g[i+][j][];
}
}
}
}
}
for(int j=;j<=up;j++){
if((fix-x<=j)&&(j<x+fix)){
ret+=f[][j][]+f[][j][];
}
}
}
}
return ret;
}
int main(){
scanf("%lld%lld",&L,&R);
scanf("%d",&m);
L--;
cnt=;
while(L){
a[++cnt]=L%m;
L/=m;
}
if(cnt==){
ansl=;
}
else{
ansl=wrk();
} cnt=;
while(R){
a[++cnt]=R%m;
R/=m;
}
ansr=wrk();
printf("%lld",ansr-ansl);
}

法二:大众法。

直接钦定1号位置是最优位置,计算出来所有的总和ans

调整。

枚举位置p从2~cnt,表示要计算从p-1移动到p,会有多少个数的代价减少多少。

代价就是,sum(1,p-1)-sum(p,cnt)

设f[i][a-b][0/1]表示,第i位,这个sum的差值,有没有限制情况下,多少个数符合这个情况。

循环完一个p之后,

把a-b<0的f,ans-=(a-b)*f[i][a-b][0/1]

a-b>=0的不管。

这样进行cnt次,一定可以把所有的数移动到最优解的位置。

网上题解很多,代码就不贴了。(我也没写)

[SCOI2014]方伯伯的商场之旅的更多相关文章

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

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

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

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

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

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

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

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

  5. bzoj3598 [Scoi2014]方伯伯的商场之旅

    数位dp,我们肯定枚举集合的位置,但是如果每次都重新dp的话会很麻烦,所以我们可以先钦定在最低位集合,dp出代价,然后再一步步找到正确的集合点,每次更改的代价也dp算就好了. #include < ...

  6. 2019.03.28 bzoj3598: [Scoi2014]方伯伯的商场之旅(带权中位数+数位dp)

    传送门 题意咕咕咕自己读吧挺简单的 思路: 由带权中位数的性质可以得到对于每个数放在每个二进制位的代价一定是个单调或者单峰函数,因此我们先把所有的数都挪到第一个位置,然后依次向右枚举峰点(极值点)把能 ...

  7. BZOJ.3598.[SCOI2014]方伯伯的商场之旅(贪心 数位DP)

    题目链接 先考虑,对于确定的一个数,怎样移动代价最少(或者移到哪个位置最优)? 假设我们都移到下标\(1\)位置(设集合点为\(1\)),那么移动到下标\(2\)与\(1\)相比代价差为:\(下标&l ...

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

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

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

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

随机推荐

  1. Spring + SpringMVC配置

    代码结构如下 web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xs ...

  2. cli 开发记录

    最近要开发一个 cli,主要作用是方便同事生成前端项目,做了一天半,基本参考的是 vue-cli. cli 要实现的功能: 用 cnpm install zt-cli -g 全局安装,这个就要将你做的 ...

  3. html点击链接打开新窗口

    html标记中格式为<a href="url"> text </a> 此时,内容在原来窗口呈现,如果想新开窗口,可以采用下列方式. 1. <a hre ...

  4. ECMAScript6——异步操作之Promise

    Promise对象的参数为一个回调函数,这个回调函数有两个参数,分别是resolve, reject(这俩参数的名字可任取),resolve,reject分别表示异步操作执行成功后的回调函数和异步操作 ...

  5. jQuery .attr() vs. .prop()

    Property vs. Attribute 在开始正式比较prop()和attr()两个jQuery方法之前,我们有必要先弄清一下Property和Attribute两个单词的意思.在中文里面,它们 ...

  6. 【Android UI设计与开发】第01期:引导界面(一)ViewPager介绍和使用详解

    做Android开发加起来差不多也有一年多的时间了,总是想写点自己在开发中的心得体会与大家一起交流分享.共同进步,刚开始写也不知该如何下手,仔细想了一下,既然是刚开始写,那就从一个软件给人最直观的感受 ...

  7. WPF DataGrid列设置为TextBox控件的相关绑定

    在wpf的DataGrid控件中,某一列的数据模板为TextBox控件的话,绑定Text="{Binding TxtSn, UpdateSourceTrigger=PropertyChang ...

  8. 1089. Insert or Merge (25)-判断插入排序还是归并排序

    判断插入排序很好判断,不是的话那就是归并排序了. 由于归并排序区间是2.4.8开始递增的,所以要判断给出的归并排序执行到哪一步,就要k从2开始枚举. 然后再对每个子区间进行一下sort即可. #inc ...

  9. 软件工程学习之小学四则混合运算出题软件 Version 1.00 设计思路及感想

    对于小学四则混合运算出题软件的设计,通过分析设计要求,我觉得为了这个软件在今后便于功能上的扩充,可以利用上学期所学习的<编译原理>一课中的LL1语法分析及制导翻译的算法来实现.这样做的好处 ...

  10. We are a team----sh_6666

    团队宣言:编程,我们是玩命的,玩命,我们是认真的. 团队简介: 团队名称:sh_6666队 团队博客链接:http://www.cnblogs.com/sh-6666/ 人物简介: 剧团导演:吴小勇 ...