標籤:blog http os io ar strong for 2014 art
在講解反素數之前,我們先來看反素數的概念。
反素數的定義:對於任何正整數,其約數個數記為,例如,如果某個正整數滿足:對任意的正整
數,都有,那麼稱為反素數。
從反素數的定義中可以看出兩個性質:
(1)一個反素數的所有質因子必然是從2開始的連續若干個質數,因為反素數是保證約數個數為的這個數盡量小
(2)同樣的道理,如果,那麼必有
在ACM競賽中,最常見的問題如下:
(1)給定一個數,求一個最小的正整數,使得的約數個數為
(2)求出中約數個數最多的這個數
從上面的性質中可以看出,我們要求最小的,它的約數個數為,那麼可以利用搜尋來解。
以前我們求一個數的所有因子也是用搜尋,比如,以每一個為樹的一層建立搜尋樹,深度為
以為例進行說明,建樹如下:
再看一道例題:
題意:給一個數,求一個最小的正整數,使得它的因子個數為。
#include <iostream>#include <string.h>#include <stdio.h>using namespace std;typedef unsigned long long ULL;const ULL INF = ~0ULL;int p[16] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53};int n;ULL ans;void dfs(int dept,ULL tmp,int num){ if(num > n) return; if(num == n && ans > tmp) ans = tmp; for(int i=1;i<=63;i++) { if(ans / p[dept] < tmp) break; dfs(dept+1,tmp *= p[dept],num*(i+1)); }}int main(){ while(cin>>n) { ans = INF; dfs(0,1,1); cout<<ans<<endl; } return 0;}
-------------以上轉自http://blog.csdn.net/ACdreamers/article/details/25049767----------
我自己想說一下對例題代碼的理解
代碼主要部分是
int p[16] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53};int n;ULL ans;void dfs(int dept,ULL tmp,int num) //其實此處DFS即是枚舉。i的次數遞增,即是對應 //p[dept]的指數的增加。深度dept即是第幾個素數。63次方已是 //足夠大了。枚舉指數來看其約數的個數。{ if(num > n) return; if(num == n && ans > tmp) ans = tmp; for(int i=1;i<=63;i++) { if(ans / p[dept] < tmp) break; dfs(dept+1,tmp *= p[dept],num*(i+1)); }}int main(){ while(cin>>n) { .................. dfs(0,1,1); ................. } return 0;}
ZOJ 2562
緊接著,我自己就做了這一題
#include <iostream>#include <cstdio>#include <algorithm>#define LL long longusing namespace std;LL p[16] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53}; LL ans,n,c;void solve(int dep,LL tmp, LL num){if(tmp>n) return ;if(num>c||(num==c)&&tmp<ans){ans=tmp;c=num;}for(LL i=1;i<=60;i++){if(tmp*p[dep]>n) break;solve(dep+1,tmp*p[dep],num*(i+1));tmp*=p[dep];}}int main(){while(scanf("%lld",&n)!=EOF){c=0;ans=(1<<60);solve(0,1,1);printf("%lld\n",ans);}return 0;}
ZOJ 2562 反素數