題解 P4759 【[CERC2014]Sums】
阿新 • • 發佈:2020-10-16
話不多說,我們直入正題
這是一題數論題,主要考察等差數列知識。
【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;//完結撒花
}