题解 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;//完结撒花
}
posted @ 2020-10-16 19:44  泠詟  阅读(148)  评论(0)    收藏  举报