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

题目描述

方伯伯有一天去参加一个商场举办的游戏。商场派了一些工作人员排成一行。每个人面前有几堆石子。

说来也巧,位置在 \(i\) 的人面前的第 \(j\) 堆的石子的数量,刚好是 \(i\) 写成 \(K\) 进制后的第 \(j\) 位。现在方伯伯要玩一个游戏,商场会给方伯伯两个整数 \(L,R\)

方伯伯要把位置在 \([L, R]\) 中的每个人的石子都合并成一堆石子。每次操作,他可以选择一个人面前的两堆石子,将其中的一堆中的某些石子移动到另一堆,代价是移动的石子数量 \(×\times\) 移动的距离。

商场承诺,方伯伯只要完成任务,就给他一些椰子,代价越小,给他的椰子越多。所以方伯伯很着急,想请你告诉他最少的代价是多少。例如:\(10\) 进制下的位置在 \(12312\) 的人,合并石子的最少代价为:\(1 \times 2 + 2 \times 1 + 3 \times 0 + 1 \times1 + 2 \times 2 = 9\)即把所有的石子都合并在第三堆。

输入格式

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

输出格式

输出仅有 \(1\) 行,包含 \(1\) 个整数,表示最少的代价。

输入输出样例

输入 #1

3 8 3

输出 #1

5

说明/提示

对于 \(100\%\) 的数据,\(1 \le L \le R \le 10^{15}, 2 \le K \le 20\)

分析

对于一堆石子来说,显然合并到石子位置的中位数是最优的

但是题中给出的石子达到了 \(10^{15}\) ,暴力枚举显然是不现实的

但是把所有的石子都合并到同一个位置的贡献是可以计算的

所以我们考虑先把所有的石子合并到编号为 \(1\) 的一堆

然后再把石子从左往右移,每次算出减小的贡献减去

如果当前的位置在修改的位置左边,那么减小的贡献减去当前的数字

否则减小的贡献加上当前的数字

因为递归时从编号较大的石子递归到编号较小的石子

所以减小的贡献一定是先增大后减小的

因此为了防止数组越界,当当前值小于 \(0\) 时,直接 \(return 0\)

代码

#include<cstdio>
#include<cstring>
#define ll long long
#define rg register
const int maxk=65,maxm=1e4+5;
ll f[maxk][maxm],l,r;
int num[maxk],cnt,k;
ll dfs(ll ws,ll tot,bool lim){
	if(!ws) return tot;
	if(!lim && f[ws][tot]!=-1) return f[ws][tot];
	int up=lim?num[ws]:(k-1);
	long long ans=0;
	for(int i=0;i<=up;i++){
		ans+=dfs(ws-1,tot+i*(ws-1),lim && i==up);
	}
	if(!lim) f[ws][tot]=ans;
	return ans;
}
ll dfs2(ll ws,ll tot,int xg,bool lim){
	if(tot<0) return 0;
	if(!ws) return tot;
	if(!lim && f[ws][tot]!=-1) return f[ws][tot];
	int up=lim?num[ws]:(k-1);
	long long ans=0;
	for(int i=0;i<=up;i++){
		ans+=dfs2(ws-1,tot+(ws<xg?-i:i),xg,lim && i==up);
	}
	if(!lim) f[ws][tot]=ans;
	return ans;
}
ll solve(ll now){
	cnt=0;
	while(now){
		num[++cnt]=now%k;
		now/=k;
	}
	memset(f,-1,sizeof(f));
	long long nans=dfs(cnt,0,1);
	for(int i=2;i<=cnt;i++){
		memset(f,-1,sizeof(f));
		nans-=dfs2(cnt,0,i,1);
	}
	return nans;
}
int main(){
	scanf("%lld%lld%d",&l,&r,&k);
	printf("%lld\n",solve(r)-solve(l-1));
	return 0;
}
posted @ 2020-10-11 09:06  liuchanglc  阅读(105)  评论(0编辑  收藏  举报