hdu 4133

由於上一次做的線段樹用到反素數,覺得很神奇,所以在這學習了一下。

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=4133

關於反素數的定義參見百度百科:http://baike.baidu.com/view/2621997.htm

 

關鍵還是代碼,參照反素數性質剪枝搜索。關於我的理解都寫在代碼註釋裏了。代碼就是百度百科的

#include <stdio.h>
#include <string.h>

/*性質一:一個反素數的質因子必然是從2開始連續的質數.*/

const __int64 prime[16] = {1,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47};

__int64 maxsum, bestnum, n;//maxsum最優解時的因數個數, bestnum是最優解

/*
num:當前枚舉到的數,k:枚舉到的第k大的質因子;sum:該數的約數個數;limit:質因子個數上限;
*/

void dfs(__int64 num, __int64 k, __int64 sum, __int64 limit)
{
	if (sum > maxsum)   //如果約數個數更多,將最優解更新爲當前數;
	{
		maxsum = sum;
		bestnum = num;
	}
	else if (sum == maxsum && bestnum > num)
	{
		bestnum = num; //如果約數個數相同,將最優解更新爲較小的數;
	}
	if (k>15)//枚舉的數超過 prime數組元素個數。 
	{
		return;
	}
	__int64 temp = num, i;
	for (i=1; i<=limit; i++)//利用性質2:p=2^t1*3^t2*5^t3*7^t4.....必然t1>=t2>=t3>=....
	{
		if (temp * prime[k] > n)
		{
			break;
		}
		
		/*
			temp爲乘上一個第k個質因數的值 
			k+1是指向下一個質因數
			sum*(i+1): 假設 p=2^t1*3^t2*5^t3*7^t4,則他的約數個數是(t1+1)*(t2+1)*(t3+1)*(t4+1)
			加一的原因自己想想應該很簡單 
			所以sum*(i+1)就是temp的約數個數 
			i就是下一個質因數的上限,就是性質2;
		*/
		 
		temp = temp * prime[k];
		dfs(temp, k+1, sum * (i+1), i); 
	}
}
int main()
{
	int T, Cas = 1;
	scanf("%d", &T);
	while (T--)
	{
		maxsum = 0;
		bestnum = 0;
		scanf("%I64d", &n);
		dfs(1, 1, 1, 50); //k要從1開始,因爲prime[0] = 1;1不是質因數 
		printf("Case #%d: %I64d\n", Cas++, bestnum);
	}
}


 

發佈了32 篇原創文章 · 獲贊 1 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章