题意
对于一个数
x
x
x,每次贪心地找到不小于剩下的数的最大的正整数的立方,减去这个数,并重复直至变成
0
0
0,操作次数即为
x
x
x的贡献。
在
[
1
,
m
]
[1,m]
[1,m]中找到最大的贡献及对应的数最大值。
思路
其他题解给出了二分/ d f s dfs dfs的做法,这里给出一种 D P DP DP的做法。
将 m m m分解为 ∑ a k 3 t k \sum{a_k^{3}t_k} ∑ak3tk,其实总共分解出来的数不多,考虑可以通过以下方式计算答案:枚举 k k k,选取 a k 3 a_k^3 ak3的最后一个,不小于 a k 3 a_k^3 ak3的都保留,小于的都忽视,将 a k 3 a_k^3 ak3其拆开成最优的方案,与不小于 a k 3 a_k^3 ak3的贡献合起来。
接下来就考虑 x 3 x^3 x3的贡献:将 x 3 − 1 x^3-1 x3−1分解,按照上面的方法计算,最后考虑 x 3 x^3 x3本身。
时间复杂度为 O ( m 3 ) O(\sqrt[3]{m}) O(3m),答案最大也只有 18 18 18,常数可以接受。
Code
#include<bits/stdc++.h>
#define mid ((l+r)>>1)
#define hehe pair<long long,long long>
#define fir first
#define sec second
#define pb push_back
#define inf 1000000007
#define N 100005
using namespace std;
long long read()
{
long long x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<1ll)+(x<<3ll)+ch-48,ch=getchar();
return x*f;
}
void write(long long x)
{
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+'0');
}
long long n,cb[N],lim;
vector<hehe>v;
hehe ans,f[N];
long long cube(long long x)
{
return x*x*x;
}
long long ncb(long long x)
{
return (long long)pow((double)x,(double)1/(double)3);
}
void solve(long long x)
{
v.clear();
for(long long t,d;x;)
{
t=ncb(x);
while(cb[t]>x)t--;
while(t<lim&&cb[t+1]<=x)t++;
d=x/cb[t];
v.pb({t,d});
x-=d*cb[t];
}
}
hehe dp(long long x)
{
long long sum=0,total=0;
hehe ans={0,0};
for(auto &aut:v)
{
long long t=aut.fir,d=aut.sec;
long long temp=sum+(d-1)+f[t].fir,size=total+cb[t]*(d-1)+f[t].sec;
if(temp>ans.fir||(temp==ans.fir&&size>ans.sec))ans.fir=temp,ans.sec=size;
sum+=d;
total+=d*cb[t];
}
return ans;
}
int main()
{
n=read();
lim=ncb(n)+2;
for(long long i=1;i<=lim;i++)
{
cb[i]=cube(i);
}
for(long long i=1;i<=lim;i++)
{
long long temp=cb[i]-1;
solve(temp);
f[i]=dp(temp);
if(!f[i].fir)f[i].fir=i,f[i].sec=cb[i];
}
solve(n);
ans=dp(n);
printf("%lld %lld\n",ans.fir,ans.sec);
return 0;
}