由於上一次做的線段樹用到反素數,覺得很神奇,所以在這學習了一下。
題目鏈接: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);
}
}