UVa 1575 Factors

链接

题意:

令f(k)=n 表示 有n种方式,可以把正整数k表示成几个数的乘积的形式。

例 10=2*5=5*2,所以f(10)=2

给出n,求最小的k

 

组合数忘了开long long 连WA15次 我真的傻了。

 

这个和反素数有点像

从最小的质数开始枚举选几个

假设前i-1个种质数用了k个,有Np种方案,第i种质数选a个,

那么前i种质数的方案就有Np*C[k+a][a]

可以理解原来有k个位置,又加了a个位置,有a个数可以放在任意位置

所以前i种的每一种方案都变成C[k+a][a]种

 

枚举每个质数选几个时,如果上一个质数选了k个,那么这一个质数最多选k个

假设这个质数选了k+1个,那么显然上一个质数选k+1个,这个选k个更优

 

 1 #include <cctype>
 2 #include <cstdio>
 3 
 4 typedef unsigned long long LL;
 5 
 6 const int MAXN=100;
 7 
 8 LL ans,n;
 9 
10 LL C[MAXN][MAXN];
11 
12 int prime[21]={0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71};
13 
14 inline void pre() {
15     C[0][0]=1;
16     for(int i=1;i<70;i++) {
17         C[i][0]=1;
18         for(int j=1;j<=i;j++)
19             C[i][j]=C[i-1][j-1]+C[i-1][j];
20     }
21 }
22 
23 void dfs(int num,int limit,LL Np,LL Ans,int last) {
24     if(Ans>ans) return;
25     if(Np==n) {ans=Ans;return;}
26     if(Np>n||num>20) return;
27     LL t=1;
28     for(int i=1;i<=limit;++i) {
29         t*=prime[num];
30         if(Ans>=ans/t) return;
31         dfs(num+1,i,Np*C[last+i][i],Ans*t,last+i);
32     }
33 }
34 
35 int hh() {
36     pre();
37     while(scanf("%lld",&n)!=EOF) {
38         if(n==1) printf("1 2\n");
39         else {
40             ans=(LL)1<<63;
41             dfs(1,63,1,1,0);
42             printf("%lld ",n);
43             printf("%lld\n",ans);
44         }
45     }
46     return 0;
47 }
48 
49 int sb=hh();
50 int main(int argc,char**argv) {;}
代码

 

posted @ 2017-09-22 18:59  拿叉插猹哈  阅读(177)  评论(0编辑  收藏  举报