1. 程式人生 > >PAT-ADVANCED1096——Consecutive Factors

PAT-ADVANCED1096——Consecutive Factors

題目描述:

題目翻譯:

1096 連續因子

在正整數N的所有因子中,可能存在幾個連續的數字。 例如,630可以被考慮為3×5×6×7,其中5,6和7是三個連續的數字。 現在給出任何正N,你應該找到連續因子的最大數量,並列出連續因子的最小序列。

輸入格式:

每個輸出檔案包含一個測試用例,其給出了一個正整數N(1 < N < 2 ^ 31)。

輸出格式:

對每個測試用例,在第一行中輸出連續因子的最大個數。在第二行中,以形式——factor[1]*factor[2]*...*factor[k],輸出連續因子的最小序列。序列中的因子以増序排列且不包括1。

輸入樣例:

630

輸出樣例:

3
5*6*7

知識點:滑動視窗法

思路:N不會被除自己以外的大於N ^ 0.5的整數整除

題目又明確指出不包括1,因此我們的左指標只需遍歷[2, N ^ 0.5)範圍內的值即可。對於每一個左指標i,如何尋找一個右指標j呢?

我們首先令j = i,再用multiply記錄當前乘積,進入以下迴圈過程:

(1)如果在j增加的過程中,使得我們的multiply >= N,break出迴圈。

(2)如果N % ((j + 1) * multiply) != 0,break出迴圈,否則更新multiply *= j + 1。

一開始我是令N % (j + 1) != 0時跳出迴圈,但這是錯誤的。如果這麼做,對於4080這個數而言,其輸出會是2 * 3 * 4 * 5 * 6,N除以這個值的餘數不是0。因為在尋找下一個值的時候,除了要保證j + 1能被N整除外,(j + 1) * multiply也要保證能被N整除才行

。而後者如果滿足,前者一定滿足,因此我們將判斷條件改為N % ((j + 1) * multiple)。

(3)令j自增1。

時間複雜度是O(N)。空間複雜度是O(1)。

C++程式碼:

#include<iostream>
#include<cmath>

using namespace std;

int main() {
	int N;
	scanf("%d", &N);
	int left = 0, right = -1;	//[left, right]為連續整數區間 
	for(int i = 2; i < sqrt(N); i++){
		if(N % i != 0){
			continue;
		}
		int j = i;
		int multiply = i;
		while(true){
			if(multiply >= N){
				break;
			}
			if(N % ((j + 1) * multiply) == 0){
				multiply *= (j + 1);
			}else{
				break;
			}
			j++;
		}
		if(j - i > right - left){
			right = j;
			left = i;
		}
	}
	if(right - left + 1 == 0){
		printf("1\n%d", N);
		return 0;
	}
	printf("%d\n", right - left + 1);
	for(int i = left; i <= right; i++){
		printf("%d", i);
		if(i != right){
			printf("*");
		}
	}
	return 0;
}

C++解題報告: