jzoj100023 【NOIP2016提高A组模拟7.6】塔

题意

在[1,m]中选出x,使得x能按下列规则变换尽量多次,在满足尽量多次的前提下求最大的x。
1. 若x>=1,则设a为小于等于x的最大完全立方数,x=x-a,重复步骤1
2. 若x=0,退出。

分析

我们设一个双值函数 f(m) 表示x取[1,m]时的最大次数与最大x。

设a为小于等于x的最大完全立方数.
我们希望将f分解为若干小问题(分治)。
假设当前这个放a的话,那么我们就有一个新的m取值范围 m2=ma3

假设当前这个放a-1的话,那么我们就有一个新的m取值范围 m2=a31(a1)3 ,因为x即使在[1,m]的范围下,最多也只能取到 a31 ,不然就要用 a3 了。

假设当前这个放a-1的话,那么我们就有一个新的m取值范围 m2=(a1)31(a2)3 ,显然比放a-1要小。

因为2与3对次数的贡献是一样的,所以自然是m2越大越好。因为 f(x)f(x1)

所以每次只需要取1,2者尝试。时间复杂度 T(m)=T(ma3)+T(a3(a1)31)
暂时不会分析。

#include <cstdio>
#include <iostream>
#include <cmath>
typedef long long ll;
using namespace std;
ll m,a,b;
const double f3=(1/(double)3);
void solve(ll x,ll &cnt,ll &X) {
    if (x==1) {cnt=1,X=1; return;}
    if (x==0) {cnt=0,X=0; return;}
    ll mx=pow(x,f3);
    ll a1,a2,b1,b2;
    solve(x-mx*mx*mx,a1,b1);
    solve(mx*mx*mx-1-(mx-1)*(mx-1)*(mx-1),a2,b2);
    cnt=max(a1,a2)+1;
    if (a1>=a2) X=b1+mx*mx*mx; else X=b2+(mx-1)*(mx-1)*(mx-1);
}
int main() {
    freopen("2.in","r",stdin);
    cin>>m;
    solve(m,a,b);
    cout<<a<<" "<<b<<endl;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值