完全平方数#
题目描述#
n是一个奇数,求n个连续的非负整数,a,a+1,a+2,…,a+n−1,使得这些数的和为一个完全平方数。
求满足条件最小的a。
输入格式#
第一行是一个整数T(1≤T≤1000),表示样例的个数。
以后每行一个整数n(1≤n<109)。
输出格式#
每行依次输出一个样例的结果。
样例输入#
2 1 3样例输出#
0 2
解题思路:等差数列前n项求和公式:Sn = n*(2a + n-1)/2 = n*(a + (n-1)/2). 令 t = (n-1)/2. 所以 Sn = n*(a + t)。
- 要令Sn = i^2 , 最直接的是 i = n, 则 a = (n+1)/2 。这答案也是无“更优解”的时候的解。
- 前面也写过质因数分解,知道 每个数都可以被分解成 质因数的乘积。 所以什么时候可能有更优解? 当 n 有平方因子的时候。 因为这时候可以对 n 进行化简。 设 n = c^2 * n0;
- 令化简之后的 n0*(a + t) = i' ^2, 可能比 1. 有更小的 a 解。此时 从 i'' = 0 开始枚举,找到a的值: a = i'' ^2 * n0 - t >= 0.
- 各等式的关系式: Sn = n*(a + t) = c^2 * n0*(a + t) = i^2; n0*(a + t) = i' ^2........@2; i'' * n0 = i'
- 最后一步为啥还要 把 i' 转换成 i'' * n0,因为如果直接对 @2 式子移项计算 a ,a = i'^2 / n0 - t,则还需要验证 i^2 能否整除 n0, 换成乘法运算就不需要这一步的验证。
AC代码:
#include <stdio.h>
const int MAXN = 1e9;
int square[32000] = {0};
int main()
{
int cnt = 0;
for (int i = 1; i*i <= MAXN; i += 1)
square[++cnt] = i*i;
cnt ++;
square[cnt] = cnt*cnt;
int T,n,n0,a,t;
scanf("%d",&T);
while ( T --)
{
scanf("%d",&n);
n0 = n; t = (n-1)/2;
for (int i = 3; square[i] <= n0; i += 2)
while (n0%square[i] == 0)
n0 /= square[i];
if (n0 == n)
{
if (n == 1) puts("0");
else printf("%d\n",(n+1)/2);
}
else
{
for (int i = 0; ; i ++)
{
a = square[i]*n0 - t;
if (a >= 0)
{
printf("%d\n",a);
break;
}
}
}
}
return 0;
}