题解 P4759 【[CERC2014]Sums】
话不多说,我们直入正题
这是一题数论题,主要考察等差数列知识。
【part 1】题意简述
给你T个数,请把每个数拆分成几个连续自然数相加,无法拆分输出IMPOSSIBLE。
【part 2】算法&思路分析
首先,我们只考虑只有一个数的情况:
设这个数为N,N = a + (a + 1) + (a + 2) + ...+ (a + n - 1)
也就是说,起始数是a,共有n项。
接下来,我们就有两个思路:
-
枚举a
这是最容易想到的思路,可以发现一个性质:a<=n/2,所以我们要枚举n/2次,但还要继续拓展,所以时间复杂度为O(N/2*n),肯定超时
-
枚举n
这是本题正解。
N = (a+a+n-1)×n/2
因为a为正整数
所以2a+n-1>n
因此n<=sqrt(N×2)
N = (a+a+n-1)*n/2
2×N/n = 2a+n-1;
移项可以得出a = (2×N/n-n+1)/2
当a为正整数时有解。
【part 3】代码分析
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
int T , n;
int main() {
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
cin >> T;
while(T --) {
cin >> n;//输入
bool found = 1;//判断是否能找到
for(int i = 2; i <= sqrt(2 * n); i ++) {//n<sqrt(2*N)
int a = ( (2 * n) / i - i + 1) / 2;
if( (a * 2 ) == + 1 - i + ( (2 * n) / i )) {
if( (a * 2 - 1 + i ) * i == 2 * n) {
cout << n << " = ";
for(int j = 1; j <= i-1; j ++)
cout << a << " + " , a ++;
cout << a << endl;
found = 0;
break;
}//判断a是否为整数,若为整数则输出
}//时刻注意double精度误差!
}
if(found) cout << "IMPOSSIBLE" << endl;
}
return 0;//完结撒花
}

浙公网安备 33010602011771号