【SCOI2014】方伯伯的商场之旅【数位dp】【单峰函数】

题意:给定 l , r , k l,r,k l,r,k ,对于一个 k k k 进制数,将数码看成这个位置的石子个数,每将一个石子移动 1 1 1 的距离需要 1 1 1 的代价。求 [ l , r ] [l,r] [l,r] 中的所有数在 k k k 进制下将石子集中在一个位置的最小代价之和。

l ≤ r ≤ 1 0 15 , k ≤ 20 l\leq r\leq 10^{15},k\leq 20 lr1015,k20

对于序列 { a 1 , a 2 , … , a n } \{a_1,a_2,\dots,a_n\} {a1,a2,,an},显然将集中位置从 k − 1 k-1 k1 移动到 k k k 会减少 ∑ i = k n a i − ∑ i = 1 k − 1 a i \sum_{i=k}^n a_i-\sum_{i=1}^{k-1}a_i i=knaii=1k1ai 的代价。

枚举最优的位置,卡下前后的和的上下界,就可以数位 dp 了。

然而这个东西十分精神污染,反正我写了一天没写出来。

考虑更优美的做法。发现这个代价是关于集中位置的单峰函数,也就是一次往后移动如果贡献为负,那之后的贡献都为负。

所以有这样一个思路:先统计出放在最高位的总贡献,然后考虑每个移动产生的贡献,如果为正就把它加上。

可以设 d p ( p , i , s , l i m ) dp(p,i,s,lim) dp(p,i,s,lim) 表示从高到低考虑到第 i i i 位,如果把未考虑的记为 0 0 0,高于 p p p (含)的数码和减去低于 p p p (不含)的数码和为 s s s,是否卡上界的总贡献。 p = 1 p=1 p=1 的时候因为要算总贡献,要特殊处理一下。

为什么数位 dp 记忆化搜索这么好写啊……

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
using namespace std;
typedef long long ll;
int B;
int a[55],cnt,p;
ll f[55][20005];
ll dfs(int i,int s,int lim)
{
	if (!i||s<0) return max(s,0);
	if (!lim&&~f[i][s]) return f[i][s];
	int mx=lim? a[i]:B-1;
	ll ans=0;
	for (int x=0;x<=mx;x++)
		ans+=dfs(i-1,s+(p==1? x*(i-1):(i<p? -x:x)),lim&&x==mx);
	if (!lim) f[i][s]=ans;
	return ans;
}
inline ll calc(ll n)
{
	cnt=0;
	while (n) a[++cnt]=n%B,n/=B;
	memset(f,-1,sizeof(f)),p=1;
	ll ans=dfs(cnt,0,1);
	for (p=2;p<=cnt;p++) memset(f,-1,sizeof(f)),ans-=dfs(cnt,0,1);
	return ans; 
}
int main()
{
	ll l,r;
	cin>>l>>r>>B;
	cout<<calc(r)-calc(l-1);
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
项目:使用AngularJs编写的简单 益智游戏(附源代码)  这是一个简单的 javascript 项目。这是一个拼图游戏,也包含一个填字游戏。这个游戏玩起来很棒。有两个不同的版本可以玩这个游戏。你也可以玩填字游戏。 关于游戏 这款游戏的玩法很简单。如上所述,它包含拼图和填字游戏。您可以通过移动图像来玩滑动拼图。您还可以选择要在滑动面板中拥有的列数和网格数。 另一个是填字游戏。在这里你只需要找到浏览器左侧提到的那些单词。 要运行此游戏,您需要在系统上安装浏览器。下载并在代码编辑器中打开此项目。然后有一个 index.html 文件可供您修改。在命令提示符中运行该文件,或者您可以直接运行索引文件。使用 Google Chrome 或 FireFox 可获得更好的用户体验。此外,这是一款多人游戏,双玩家都是人类。 这个游戏包含很多 JavaScript 验证。这个游戏很有趣,如果你能用一点 CSS 修改它,那就更好了。 总的来说,这个项目使用了很多 javascript 和 javascript 库。如果你可以添加一些具有不同颜色选项的级别,那么你一定可以利用其库来提高你的 javascript 技能。 演示: 该项目为国外大神项目,可以作为毕业设计的项目,也可以作为大作业项目,不用担心代码重复,设计重复等,如果需要对项目进行修改,需要具备一定基础知识。 注意:如果装有360等杀毒软件,可能会出现误报的情况,源码本身并无病毒,使用源码时可以关闭360,或者添加信任。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值