Codevs2461反質數

http://codevs.cn/problem/2461/

Codevs2912,洛谷P1463與此題完全相同….
雖然分別是06浙江07河南和05山東的省隊選拔賽題目…..
注意題目有問題..是求最小的反質數

思路
首先要明確一個結論:
某一個數的因子數 = 組成這個數的各質因子數的次數+1的乘積。可以由唯一分解定理和乘法原理得到。
這是我們統計因子數的計算式。
那麼我們就將一個反質數看作選取了質因子數及質因子數的次冪的乘積,DFS確定選取方案
然後爲了在因子數儘量多的前提下,使答案儘量小,對於一個反質數,則可使較小因子的次數儘量大
——實現爲:質因子從小到大選取,且後一質因子選取的次數小於前一質因子,且使總的質因子數儘量大。
對於質因子,我們可以事先寫出一些質數使用,我們發現,若每個質因子都只選一個…選了12個質因子相乘之積便>2*10^9了,故x只需選取至第11個質數即可,我們的質數表也只需寫至11位(這裏寫了13位,足夠1-10^16範圍使用,無傷大雅)。
應該注意的一點是,我們(打表)發現,隨着n的增長範圍內反質數的因子數也隨之增多..故質數表必須隨之n值增大而增大

代碼

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;
long long n,maxd,ans;
int prime[]={0,2,3,5,7,11,13,17,19,23,29,31,37,41};
void dfs(int x,long long sum,long long nowd,long long Limit)
//第幾個質數,質數乘積,sum的因子數,質因子次數限制(質因子由小到大,後面的質因子次數一定小於前面的) 
{
    if (nowd>maxd||(nowd==maxd&&sum<ans))//因子數更多或因子數相同但反質數小
    maxd=nowd,ans=sum;
    if(x>11)
    return;
    for (int i=1;sum*prime[x]<=n&&i<=Limit;i++)
    dfs(x+1,sum*=prime[x],nowd*(i+1),i);//注意nowd的統計方法
}
int main()
{
    scanf("%lld",&n);
    ans=1;
    if(n>1)
    dfs(1,1,1,1e9);
    printf("%lld\n",ans);
    return 0;  
} 

這個題在之前的 >NOIP2017清北綜合強化試題< Day6 Problem 1中就以寫到,但寫的較爲粗略和模糊,這一篇就算是對這個題的細緻補充吧。

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