1 条题解
-
0
自动搬运
来自洛谷,原作者为

18Michael
只是也总祈望光线彼端未歇的繁星。搬运于
2025-08-24 21:50:25,当前版本为作者最后更新于2022-04-18 10:41:57,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
题意
设 表示将正整数 拆分成若干不同的平方数之和的所有方案中,最大的底数最小可能是多少,如果不存在这样的拆分,则 。
定义一个数 「超重」,当且仅当存在 ,使得 。
给定 ,求 和 中「超重」的数个数。
题解
设 , 满足 ,则 。
对于第一问,当 时,可以 时间内 dp 出答案,且该范围内只有 个数无法被表示出;当 时,。
首先 时由 dp 可知都有 ,。
假设我们已经归纳证明了 时都有 ,,则 时:
若 ,则容易构造方案使得 ;否则 ,且由于 ,故 。
又由于 ,故由归纳假设知 ,因此可以构造方案使得 。
因此该结论成立,可以通过递归在 时间内求出答案。
对于第二问,由上述结论知当 且 时,,因此该范围内所有超重的数即为 的数。又由之前结论的推导过程可知该范围内恰有 个数的 值为 ,为所有的 满足 ,因此可分成 和 两部分分别统计答案。
总时间复杂度 。
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); }
- 1
信息
- ID
- 2656
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 7
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者