说句闲话:

  • 出题人这题做了半年。
  • m500m \le 500 时,贪心上界是 1385379313853793n=13853793=57×4932n=13853793=57 \times 493^2m=494m=494)。

Part 0

显然,无解是不可能的,因为 nn121^2 的和就是 nn,而 m1m \ge 1,因此这一定是合法的方案。

Part 1

设答案为 kk,求证:pkp+4p \le k \le p+4,其中 p=nm2p=\lfloor\dfrac{n}{m^2}\rfloor

证明:

  • 先证明 kpk \ge p

    k<pk<p,则 km2<pm2k \cdot m^2 < p \cdot m^2

    显然 pnm2p \le \dfrac{n}{m^2},因此 pm2np \cdot m^2 \le n

    于是,km2<pm2nk \cdot m^2 < p \cdot m^2 \le n,即 km2<nk \cdot m^2 < n

    由于每个完全平方数都不大于 m2m^2,因此 kk 个完全平方数的和最大只能是 km2k \cdot m^2

    然而,km2<nk \cdot m^2 < n,因此,kk 个完全平方数的和绝不可能等于 nn,矛盾。

    综上,k<pk<p 的假设不成立,因此 kpk \ge p得证。

  • 再证明 kp+4k \le p+4

    n=pm2+qn=p \cdot m^2 +q

    显然 pnm2<p+1p \le \dfrac{n}{m^2}<p+1,因此 pm2n<(p+1)m2p \cdot m^2 \le n<(p+1) \cdot m^2,于是 0q<m20 \le q <m^2

    根据这个定理,总有四个非负整数 e1,e2,e3,e4e_1,e_2,e_3,e_4,使得 q=(e1)2+(e2)2+(e3)2+(e4)2q=(e_1)^2+(e_2)^2+(e_3)^2+(e_4)^2

    由于 q<m2q <m^2,而 (e1)2,(e2)2,(e3)2,(e4)2(e_1)^2,(e_2)^2,(e_3)^2,(e_4)^2 均非负,因此 (e1)2,(e2)2,(e3)2,(e4)2(e_1)^2,(e_2)^2,(e_3)^2,(e_4)^2 均不大于 m2m^2,满足「不大于 m2m^2」的要求。

    qq 代入,得 n=pm2+(e1)2+(e2)2+(e3)2+(e4)2n=p \cdot m^2 +(e_1)^2+(e_2)^2+(e_3)^2+(e_4)^2

    此时,等式右边共 (p+4)(p+4) 个完全平方数,故 kp+4k \le p+4(为 00 的项可以删去,因此可能少于 (p+4)(p+4) 个),得证。

综上所述,pkp+4p \le k \le p+4原命题得证。

显然,由于 pkp+4p \le k \le p+4kk 的取值只有 55 种(ppp+1p+1p+2p+2p+3p+3p+4p+4)。因此,考虑暴力枚举 kk 的值,每次判断是否可行(若 km2<nk \cdot m^2 < n直接跳过,保证 km2nk \cdot m^2 \ge n)。

Part 2

先来考虑一种错误的解法4040 分):按照与加强前的原题O(nn)O(n\sqrt{n}) 解法类似的思路,使用完全背包求解,时间复杂度 O(nm+Q)O(nm+Q),超时。

显然,使得上述算法超时的主要原因是状态太多(对应 O(nm+Q)O(nm+Q) 中的 nn)。要想优化此算法,必须减少状态数。

我们先来看一个例子:n=50025/m=10n=50025/m=10。显然,50025=500×102+5250025=500 \times 10^2+5^2,答案是 501501

不难发现,几乎所有的完全平方数都是 m2m^2 由于正向求解遇到了困难,考虑反向求解:每次枚举 kk 的值时,先假设所有的完全平方数都是 m2m^2,再把一部分 m2m^2 修改为其它小于 m2m^2 的完全平方数,使总和减小(倒扣),反向求解。

于是,完全背包的定义发生了转变。

Part 3

定义 wjw_{j} 为:恰好倒扣 jj 至少需要修改的 m2m^2 的个数,若无法恰好倒扣 jj 则其值为 ++\infty。(1i100,j01 \le i \le 100,j \ge 0

初始状态:

  • w0=0,wj=+.w_{0}=0,w_{j}=+\infty.
  • j0.j \neq 0.
  • (解释:前者无需倒扣,后者假定无法恰好倒扣,等待更新。)

状态转移方程(顺序:按 jj 升序):

  • wj=min(wj,wj(m2x2)+1).w_{j} = \min(w_{j},w_{j-(m^2-x^2)}+1).
  • 其中 x=1,2,,m1x=1,2,\ldots,m-1,保证 j(m2x2)0.j-(m^2-x^2) \ge 0.
  • (解释:修改 11m2m^2(改为 x2x^2),倒扣 m2x2m^2-x^2。)

由于需要从 km2k \cdot m^2 倒扣至 nn,共倒扣了 km2nk \cdot m^2 - n,因此 wkm2nw_{k \cdot m^2 - n} 即为所需的答案。

注意:若 wkm2n>kw_{k \cdot m^2 - n} > k,则表明没有足够的 m2m^2 用于倒扣时的修改(或根本不可能恰好倒扣,此时 wkm2n=+w_{k \cdot m^2 -n} = +\infty),该 kk 的值必须舍去。

Part 4

求证:倒扣的总量(km2nk \cdot m^2 - n即当 i=mi=m 时下标 jj 的上界)不大于 4m214 \cdot m^2-1

证明:

前面已经证明 pm2np \cdot m^2 \le n

  • pm2<np \cdot m^2 < n 时:

    此时有 pm2n1p \cdot m^2 \le n-1,因此 pm2+4m2n+4m21p \cdot m^2 +4 \cdot m^2 \le n+4 \cdot m^2-1,即 (p+4)m2n+4m21(p+4) \cdot m^2 \le n+4 \cdot m^2-1

    又因为前面已经证明 kp+4k \le p+4,因此 km2(p+4)m2k \cdot m^2 \le (p+4) \cdot m^2

    于是 $k \cdot m^2 \le (p+4) \cdot m^2 \le n+4 \cdot m^2-1$,即 km2n+4m21k \cdot m^2 \le n+4 \cdot m^2-1

    由此可得 km2n4m21k \cdot m^2-n \le 4 \cdot m^2-1

  • pm2=np \cdot m^2 = n 时:

    显然此时 n=pm2n = p \cdot m^2。该等式右边共 pp 个完全平方数,故 k=pk =p(前面已经证明 kpk \ge p)。

    将上面两个等式代入计算,得 km2n=0k \cdot m^2 - n =0。显然 4m21>04 \cdot m^2-1>0

综上所述,km2n+4m21k \cdot m^2 \le n+4 \cdot m^2-1原命题得证。

wj+w_{j} \neq +\infty,求证:wj57w_{j} \le 57

证明:

根据上文,模拟可得,过程略去。原命题得证。

Part 5

最终,(每组数据)时间复杂度 O(m3+Q)O(m^3+Q),空间复杂度 O(m2)O(m^2),可以通过此题。

Part 6

std:

#include <bits/stdc++.h>
using namespace std;
const int M = 500 + 12;
const int K = 4 * M * M + 12;
const int W = 58;
char dp[K];
signed main()
{
   	int T;
   	scanf("%d", &T);
   	while (T--)
   	{
   		int m, Q;
   		scanf("%d %d", &m, &Q);
   		memset(dp, 0x7e, sizeof dp);
   		dp[0] = 0;
   		for (int u = 0; u <= 4 * m * m; u++)
   			for (int i = m - 1; i >= 1; i--)
   			{
   				int x = m * m - i * i;
   				if (u + x > 4 * m * m) break;
   				if (dp[u + x] > dp[u] + 1)  dp[u + x] = dp[u] + 1;
			}
		while (Q--)
		{
			long long n;
			scanf("%lld", &n);
			long long k = n / (m * m);
        	while (k * m * m < n || dp[k * m * m - n] >= W || dp[k * m * m - n] > k) k++;
        	printf("%lld\n", k);
		}
	}
    return 0;
}