给一个整数,表示成n个整数的平方和,n最小,求n。
10017 = 100^2 + 4^2 + 1 --> n = 3
这道题的快速解法要牵扯到数学定理了。
Lagrange's four-square theorem
Every natural number can be represented as the sum of four integer squares.
Legendre's three-square theorem
Let m, n be integers equal to or greater than 0. If N = 4m(8n+7), then N is NOT expressible as the sum of three squares of integers.
Example:
1584 = 42(8(12)+3) thus not in the form 4m(8n+7), so it can be expressed as the sum of 3 squares.
960 = 43(8(1)+7). Because it is of the form 4m(8n+7), it cannot be expressed as the sum of 3 squares.
Interesting Note:
For the equation N = 4m(8n+7), the (8n+7) part is equivalent to 7 mod 8. This stems from the fact that every square of a number is either 0,1, or 4 mod 8. Since this holds true for the squares of numbers, no integer congruent to 7 mod 8 can be represented as the sum of three squares. Therefore, we must have some numbers that need to be represented by the sum of four squares.
时间复杂度为O(sqrt(n))。
def solve(n): l = []; s1 = {}; for i in xrange(1, n+1): if i * i > n: break; l.append(i); s1[i * i] = 1; if s1.has_key(n): return 1; for i in l: if s1.has_key(n - i * i): return 2; while(n % 4 ==0): n /= 4; if n % 8 != 7: return 3; return 4;
int numOfSquares(int n) { if(n < 0) return 0; if(n <= 1) return 1; vector<int> f(n+1, 4); f[0] = f[1] = 1; for(int i=2; i<=n; i++) { int rt = (int)sqrt(i); if(rt*rt == i) { f[i] = 1; continue; } for(int j=1; j<=rt; j++) { f[i] = min(f[i], f[i-j*j]+1); if(f[i] == 2) break; // optional } } return f[n]; } int numOfSquares2(int n) { if(n < 0) return 0; unordered_set<int> set; int rt = (int)sqrt(n); if(rt*rt == n) return 1; for(int i=1; i<=rt; i++) { set.insert(i*i); } for(int i=1; i<=rt; i++) { if(set.count(n-i*i)) return 2; } while(n % 4 == 0) n /= 4; if(n % 8 != 7) return 3; return 4; }
Reference:
http://www.1point3acres.com/bbs/thread-17806-1-1.html
http://math453spring2009.wikidot.com/lecture-32:integers-as-sums-of-squares