求构成给定自然数的平方数的最小个数

想了很久啊,看了标签是 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;
}

 

 
posted @ 2015-09-15 20:21  wu_overflow  阅读(284)  评论(0编辑  收藏  举报