P3583 [POI2015] KWA 题解
题意
设
定义一个数
给定
题解
设
对于第一问,当
首先
假设我们已经归纳证明了
若
又由于
因此该结论成立,可以通过递归在
对于第二问,由上述结论知当
总时间复杂度
Code
#include<bits/stdc++.h>
#define LL long long
#define inf 0x3f3f3f3f
using namespace std;
int Mx=10416;
LL n,ans=0;
int f[10422];
inline LL S(LL x)
{
return x*(x+1)*(2*x+1)/6;
}
inline int get(LL x)
{
int t=pow(x*3,1.0/3);
while(S(t-1)>=x)--t;
while(S(t)<x)++t;
return t;
}
inline int F(LL x)
{
if(x<=Mx)return f[x];
int t=get(x);
return t+(F(S(t)-x)>=t);
}
int main()
{
scanf("%lld",&n);
if(n<Mx)Mx=n;
for(int i=1;i<=Mx;++i)f[i]=inf;
for(int i=1;i*i<=Mx;++i)for(int j=Mx;j>=i*i;--j)if(f[j-i*i]<inf)f[j]=min(f[j],i);
if(n<=Mx && f[n]==inf)putchar('-');
else printf("%d",F(n));
for(int i=1;i<=Mx;++i)ans+=(f[i]==inf || S(f[i]-1)>i);
if(Mx<n)
{
int t=get(n);
ans+=31LL*(t-32);
for(int i=1;i<=128;++i)ans+=(f[i]==inf && S(t)-i<=n);
}
return 0&printf(" %lld",ans);
}