@description@

TonyFang 打算送你一些立方体。

你需要在 [1, n] 中选择一个整数 k。在送你的立方体的体积和不超过 k 的情况下,TonyFang 会不断给你一个边长为正整数且尽可能大的立方体。

你需要求出最多能得到多少个立方体,以及在此条件下,k 的最小值和最大值。

input

一行一个整数 n。

output

三行,每行一个整数,分别表示最多立方体个数,容量最小值和容量最大值。

sample input

14

sample output

7

7

14

对于 100% 的数据,1≤n≤10^15。

@solution@

根据题目可以写出一个简单的 dp 求出每一个 k 能得到的立方体个数:dp[k] = dp[k-x^3] + 1。

其中 x 表示 k 的立方根下取整。

有一个小小的性质:当 x 足够大时,2*x^3 > (x+1)^3。通过函数增长速率可以得到这个结论。

这意味着当 x 足够大时,同一大小的立方体只会被赠予一次,否则就可以赠予更大的立方体。

考虑询问 1~n 的中的答案,我们可以将 1~n 分为两块:1~v^3-1 与 v^3~n,其中 v 是 n 的立方根下取整。

因为 n <= 10^15,v 的取值最多只有 10^5。现在假设我们可以通过某种手段预处理出 1~v^3-1 的答案,询问 v^3~n 的答案是多少。

由我们上面那个 dp,可以得到 dp[v^3+d] = dp[d] + 1,现在问题转变为求解 0~n-v^3 的答案,再通过一点小小的变化即可得到 v^3~n 的答案。

可以发现这是一个与原问题类似,只是规模更小的子问题。

这样递归,由我们推导的性质可得,每次问题的规模至少减为原规模一半,故只会递归 log 次。

同时为了保证上面的性质成立(即要求 x 足够大的条件成立),我们可以预先处理出 1~50^3 (50^3 = 1.25*10^5)中的所有答案,当规模在这个范围的时候可以直接得到答案。

再考虑怎么预处理 1~v^3 的答案。可以将它拆成 1~(v-1)^3-1 与 (v-1)3~v3,然后仿照上面的方法即可。

题解中采用的是贪心的做法,但我觉得可能这个方法(对我而言)要直观一些。

@accepted code@

#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN = 125000 - 1;
const int MAXM = 100000;
typedef long long ll;
ll dp[MAXN + 5], f1[MAXN + 5], f2[MAXN + 5], f3[MAXN + 5];
ll g1[MAXM + 5], g2[MAXM + 5], g3[MAXM + 5];
ll pow3(ll x) {return x*x*x;}
ll cub(ll x) {
ll le = 1, ri = MAXM;
while( le < ri ) {
ll mid = (le + ri + 1) >> 1;
if( pow3(mid) > x ) ri = mid - 1;
else le = mid;
}
return le;
}
void update(ll a, ll b, ll c, ll &x, ll &y, ll &z) {
if( a > x )
x = a, y = b, z = c;
else if( a == x )
y = min(y, b), z = max(z, c);
}
void solve(ll x, ll ri, ll &a, ll &b, ll &c) {
ll le = pow3(x);
if( ri-le <= MAXN )
a = f1[ri-le], b = f2[ri-le], c = f3[ri-le];
else {
ll p = cub(ri-le);
solve(p, ri-le, a, b, c);
update(g1[p-1], g2[p-1], g3[p-1], a, b, c);
}
a++, b += le, c += le;
}
void init() {
int x = 1;
for(int i=1;i<=MAXN;i++)
dp[i] = dp[i-pow3(cub(i))] + 1;
for(int i=1;i<=MAXN;i++) {
f1[i] = dp[i], f2[i] = f3[i] = i;
update(f1[i-1], f2[i-1], f3[i-1], f1[i], f2[i], f3[i]);
}
for(int i=1;i<MAXM;i++) {
ll x = pow3(i+1);
if( x-1 <= MAXN )
g1[i] = f1[x-1], g2[i] = f2[x-1], g3[i] = f3[x-1];
else {
solve(i, x-1, g1[i], g2[i], g3[i]);
update(g1[i-1], g2[i-1], g3[i-1], g1[i], g2[i], g3[i]);
}
}
}
int main() {
ll n; init();
scanf("%lld", &n);
if( n <= MAXN ) {
printf("%lld\n%lld\n%lld\n", f1[n], f2[n], f3[n]);
return 0;
}
ll x = cub(n), res1, res2, res3;
solve(x, n, res1, res2, res3);
update(g1[x-1], g2[x-1], g3[x-1], res1, res2, res3);
printf("%lld\n%lld\n%lld\n", res1, res2, res3);
}

@details@

好像 zxb 大佬用了打表+二分跑得飞快。。。总耗时 0ms。。。

感觉这道题乱搞的方法好多啊。

然而正解的贪心基本没人写23333

@noi.ac - 171@ 立方体的更多相关文章

  1. # NOI.AC省选赛 第五场T1 子集,与&最大值

    NOI.AC省选赛 第五场T1 A. Mas的童年 题目链接 http://noi.ac/problem/309 思路 0x00 \(n^2\)的暴力挺简单的. ans=max(ans,xor[j-1 ...

  2. NOI.ac #31 MST DP、哈希

    题目传送门:http://noi.ac/problem/31 一道思路好题考虑模拟$Kruskal$的加边方式,然后能够发现非最小生成树边只能在一个已经由边权更小的边连成的连通块中,而树边一定会让两个 ...

  3. NOI.AC NOIP模拟赛 第五场 游记

    NOI.AC NOIP模拟赛 第五场 游记 count 题目大意: 长度为\(n+1(n\le10^5)\)的序列\(A\),其中的每个数都是不大于\(n\)的正整数,且\(n\)以内每个正整数至少出 ...

  4. NOI.AC NOIP模拟赛 第六场 游记

    NOI.AC NOIP模拟赛 第六场 游记 queen 题目大意: 在一个\(n\times n(n\le10^5)\)的棋盘上,放有\(m(m\le10^5)\)个皇后,其中每一个皇后都可以向上.下 ...

  5. NOI.AC NOIP模拟赛 第二场 补记

    NOI.AC NOIP模拟赛 第二场 补记 palindrome 题目大意: 同[CEOI2017]Palindromic Partitions string 同[TC11326]Impossible ...

  6. NOI.AC NOIP模拟赛 第一场 补记

    NOI.AC NOIP模拟赛 第一场 补记 candy 题目大意: 有两个超市,每个超市有\(n(n\le10^5)\)个糖,每个糖\(W\)元.每颗糖有一个愉悦度,其中,第一家商店中的第\(i\)颗 ...

  7. NOI.AC NOIP模拟赛 第四场 补记

    NOI.AC NOIP模拟赛 第四场 补记 子图 题目大意: 一张\(n(n\le5\times10^5)\)个点,\(m(m\le5\times10^5)\)条边的无向图.删去第\(i\)条边需要\ ...

  8. NOI.AC NOIP模拟赛 第三场 补记

    NOI.AC NOIP模拟赛 第三场 补记 列队 题目大意: 给定一个\(n\times m(n,m\le1000)\)的矩阵,每个格子上有一个数\(w_{i,j}\).保证\(w_{i,j}\)互不 ...

  9. NOI.AC WC模拟赛

    4C(容斥) http://noi.ac/contest/56/problem/25 同时交换一行或一列对答案显然没有影响,于是将行列均从大到小排序,每次处理限制相同的一段行列(呈一个L形). 问题变 ...

随机推荐

  1. 命令模式(Command、Recevier、Invoker)(电脑开机命令)

    (将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能.) 在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是 ...

  2. Ubuntu 安装 RabbitMQ 和PHP扩展 - CSDN博客

    1.ubuntu16.04中安装RabbitMQ 1).首先必须要有Erlang环境支持 安装之前要装一些必要的库: sudo apt-get install build-essential  sud ...

  3. CEF 框架使用集锦

    CEF 框架使用集锦: 参考:〓https://github.com/NetDimension/NanUI/wiki/%E5%BC%80%E5%A7%8B%E4%BD%BF%E7%94%A8NanUI ...

  4. windows中将网络共享文件夹映射为网络硬盘

    目的是: 实现局域网,不同电脑之间共享文件. 例如: 计划将A电脑 的文件夹C:\MM ,共享给局域网电脑 B. 局域网所有电脑都可访问: 1. 在A电脑中 共享文件夹..选择‘启用网络发现’   ‘ ...

  5. python3.7的celery报错TypeError: wrap_socket() got an unexpected keyword argument '_context'

    原启动方法为: 起执行任务的服务 elery worker -A celery_task -l info -P eventlet 起提交任务的服务 celery beat -A celery_task ...

  6. oracle 写存储过程有返回值时 注意在loop循环处添加返回值:=

    例子: create or replace procedure p_xl is v_count NUMBER(10); begin for rs in(select yhbh from dbyh) l ...

  7. pytest相关资源收集

    pytest官网 https://docs.pytest.org/en/latest/getting-started.html 官网推荐的plugin https://docs.pytest.org/ ...

  8. 如何在liferay 7 mvc-portlet中调用service-builder项目生成的service

    不想写了,贴大神帖子 https://web.liferay.com/web/zhao.jin/blog/-/blogs/creating-service-builder-mvc-portlet-in ...

  9. 【Java-加密算法】对称加密、非对称加密、单向散列(转)

    一提到加密,就会联想到数字签名,这两个经常被混淆的概念到底是什么呢? 加密:加密是一种以密码方式发送信息的方法.只有拥有正确密钥的人才能解开这个信息的密码.对于其他人来说,这个信息看起来就像是一系列随 ...

  10. js(jquery)鼠标移入移出事件时,出现闪烁、隐藏显示隐藏显示不停切换的情况

    <script> $(".guanzhu").hover(function(){ $(".weixinTop").show(); },functio ...