1. 程式人生 > >[HNOI2001]求正整數

[HNOI2001]求正整數

return 註意 rime prev 同時 ssi ems out 過大

題目描述

對於任意輸入的正整數n,請編程求出具有n個不同因子的最小正整數m。

例如:n=4,則m=6,因為6有4個不同整數因子1,2,3,6;而且是最小的有4個因子的整數。

輸入輸出格式

輸入格式:

n(1≤n≤50000)

輸出格式:

m

輸入輸出樣例

輸入樣例#1:
INT.IN                 
4
輸出樣例#1:
INT.OUT
6
題解:

這道題和[HAOI 2007]反素數ant解題思路和方法簡直一毛一樣...

同樣我們引入這個公式:

對任一整數a1,有a=p1a1p2a2pnan,其中p1<p2<<pn均為素數,而a1,a2…,an是正整數。

a的正約數個數為:(1+a1)(1+a2)(1+an)

同理,我們也是求有n個因數的最小整數。

我們最壞的情況所有質數只取1個,由於15<log250000<16

由於數字過大,這裏用指數形式保存,用於比較大小

同時註意每層循環枚舉取質數的個數時候,因為不合法的情況很多,可以只枚舉√n次,然後用枚舉的值算出對應的另外一個值。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 using namespace std;
 7
int len,p[21],prime[21],n,ans[21]; 8 double lg[21],maxx=2e9; 9 void print(int x) 10 {int i,j,k; 11 long long s[100001],Mod=1e4; 12 memset(s,0,sizeof(s)); 13 s[1]=1;len=1; 14 for (i=1;i<=x;i++) 15 { 16 for (j=1;j<=ans[i];j++) 17 { 18 for (k=1;k<=len;k++)
19 { 20 s[k]=s[k]*prime[i]; 21 } 22 for (k=1;k<=len;k++) 23 s[k+1]+=s[k]/Mod,s[k]%=Mod; 24 while (s[len+1]) len++; 25 } 26 } 27 for (i=len;i>=1;i--) 28 if (i!=len) 29 printf("%04d",s[i]); 30 else printf("%d",s[i]); 31 } 32 void dfs(double s,int x,int k) 33 {int i; 34 if (s>=maxx) return; 35 if (k==1) 36 { 37 maxx=s; 38 memcpy(ans,p,sizeof(ans)); 39 return; 40 } 41 if (x>16) return; 42 //cout<<p[x-1]<<endl; 43 for (i=0;(i+1)*(i+1)<=k;i++) 44 if (k%(i+1)==0) 45 { 46 if (i!=0) 47 { 48 p[x]=i; 49 dfs(s+i*lg[x],x+1,k/(i+1)); 50 p[x]=0; 51 } 52 if ((i+1)*(i+1)!=k) 53 { 54 p[x]=k/(i+1)-1; 55 dfs(s+p[x]*lg[x],x+1,i+1); 56 p[x]=0; 57 } 58 } 59 } 60 int main() 61 {int i; 62 cin>>n; 63 prime[1]=2;prime[2]=3;prime[3]=5;prime[4]=7;prime[5]=11; 64 prime[6]=13;prime[7]=17;prime[8]=19;prime[9]=23; 65 prime[10]=29;prime[11]=31;prime[12]=37;prime[13]=41; 66 prime[14]=43;prime[15]=47;prime[16]=53; 67 for (i=1;i<=16;i++) 68 lg[i]=(double)log(prime[i]); 69 dfs(0,1,n); 70 //for (i=1;i<=16;i++) 71 //cout<<ans[i]<<endl; 72 print(17); 73 }

[HNOI2001]求正整數