求构成给定自然数的平方数的最小个数
想了很久啊,看了标签是 DP,所以考虑之后自己琢磨出了个策略,结果还是不对啊,各种 test case 过不去。
后来才发现这其实还可以用更为简单的方法——数学定理
对没错,所以说世界上只有两种程序员:懂数学的和不懂数学的。
// 四平方定理,又称 Lagrange's four-square theorem,
// 大意是,对于任意自然数,都可以表示为不多于四个平方数的和.
int numSquares(int n)
{
// 因子包含 4 的数在除 4 后,不影响其包含的平方数的个数.
while(n % 4 == 0){
n /= 4;
}
// 可被分解成形式为 4^a * (8 * b + 7) 的数,包含的平方数个数为 4.
if (n % 8 == 7){
return 4;
}
// 寻找一个数,使 n 与其平方的差是一个平方数.
for(int factor = 0;;++factor){
auto square = factor * factor;
// 若其平方已大于 n,则停止搜索.
if (square > n){
break;
}
auto possibleFactor = static_cast<int>(sqrt(n - square));
if (possibleFactor * possibleFactor + square == n){
// 若 factor 为零,则 n 本身就是平方数,故返回 1.
return factor == 0? 1 : 2;
}
}
// 若以上条件均不满足,则 n 必然由三个平方数构成。
return 3;
}