https://vjudge.net/problem/UVA-1575
题意:
令f(k)=n 表示 有n种方式,可以把正整数k表示成几个数的乘积的形式。
例 10=2*5=5*2,所以f(10)=2
给出n,求最小的k
搜索
从最小的质数开始枚举选几个
假设前i-1个种质数用了k个,有sum种方案,第i种质数选a个,
那么前i种质数的方案就有sum*C[k+a][a]
可以理解原来有k个位置,又加了a个位置,有a个数可以放在任意位置
所以前i种的每一种方案都变成C[k+a][a]种
枚举每个质数选几个时,如果上一个质数选了k个,那么这一个质数最多选k个
假设这个质数选了k+1个,那么显然上一个质数选k+1个,这个选k个更优
注意整数类型上限
#include<cstdio> #include<iostream> using namespace std; typedef unsigned long long LL; int p[21]={0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71}; LL ans,n; LL C[70][70]; void solve(int num,int lim,LL tot,LL now,int last) { if(now>ans) return; if(tot==n) { ans=now; return ; } if(tot>n || num>20) return; LL t=1; for(int i=1;i<=lim;i++) { t*=p[num]; if(now>=ans/t) return; solve(num+1,i,tot*C[last+i][i],now*t,last+i); } } int main() { C[0][0]=1; for(int i=1;i<70;i++) { C[i][0]=1; for(int j=1;j<=i;j++) C[i][j]=C[i-1][j-1]+C[i-1][j]; } while(scanf("%lld",&n)!=EOF) { if(n==1) { printf("1 2\n"); continue; } ans=(LL)1<<63; solve(1,63,1,1,0); printf("%lld %lld\n",n,ans); } }
时间: 2024-12-18 23:11:32