描述
一天,小B学习了分解质因数的相关内容。他发现,一个数的质因子可以有许多不同的排列方式,例如20=2 * 2 * 5=2 * 5 * 2=5 * 2 * 2,
那么小B认为20的质因子有3种不同的排列方式。小B的同学现在有一个问题:如果一个整数的质因子的不同的排列方式的种类数为k,那么这个整数n(n>1)最小是多少?小B的同学一共有T个不同的k值,希望小B帮助这个同学解决问题。但是小B发现T太大了,并且给出的k值也相当大,因此小B向你求助。
输入
第一行,一个整数T。 接下来的T行,每行一个整数k。
输出
T行,每行一个整数,其中第i行的整数表示第i个k值对应的n的值。
样例输入
4
1
2
3
105
样例输出
2
6
12
720
数据范围:
对于30%的数据,1<n<=100000; 对于全部的数据,1<n<2^63 1<k<2^63,1<=T<=1000。
先推结论
对于一个数S可以分解为
S = x 1 a 1 ∗ x 2 a 2 ∗ . . . ∗ x n a n S=x_{1}^{a_{1}}*x_{2}^{a_{2}}*...*x_{n}^{a_{n}} S=x1a1∗x2a2∗...∗xnan
那么方案数就是=:(这里为方便表示设sum= x 1 + x 2 + . . + x n x_{1}+x_{2}+..+x_{n} x1+x2+..+xn)
F ( S ) = P s u m s u m P x 1 x 1 ∗ P x 2 x 2 ∗ . . . ∗ P x n x n F(S)=\frac{P_{sum}^{sum}}{P_{x_{1}}^{x_{1}}*P_{x_{2}}^{x_{2}}*...*P_{x_{n}}^{x_{n}}} F(S)=Px1x1∗Px2x2∗...∗PxnxnPsumsum
意思是sum个数全排列后分别除掉n种数各自内部的全排列,这样就可以得到排列方案。但我们不可能一个一个去求,所以考虑两种情况。
对于 T = S ∗ p r i m e [ i ] T=S*prime[i] T=S∗prime[i]
如果S中已经有了 p r i m e [ i ] prime[i] prime[i] 那么新的方案数为
P s u m + 1 s u m + 1 P x 1 x 1 ∗ P x 2 x 2 ∗ . . . ∗ P x i + 1 x i + 1 ∗ . . . ∗ P x n x n \frac{P_{sum+1}^{sum+1}}{P_{x_{1}}^{x_{1}}*P_{x_{2}}^{x_{2}}*...*P_{x_{i}+1}^{x_{i}+1}*...*P_{x_{n}}^{x_{n}}} Px1x1∗Px2x2∗...∗Pxi+1xi+1∗...∗PxnxnPsum+1sum+1
那么可以用排列展开发现:
F ( T ) = F ( S ) ∗ ( s u m + 1 ) ∗ P x i x i P x i + 1 x i + 1 = F ( S ) ∗ s u m + 1 x i + 1 F(T)=F(S)*\frac{(sum+1)*P_{x_{i}}^{x_{i}}}{P_{x_{i}+1}^{x_{i}+1}}=F(S)*\frac{sum+1}{x_{i}+1} F(T)=F(S)∗Pxi+1xi+1(sum+1)∗Pxixi=F(S)∗xi+1sum+1
然后我们可以奇妙地发现:当S中没有 p r i m e [ i ] prime[i] prime[i]时,上述公式依然成立。
做法
其实做下来合法的方案也不是特别多,用到的最多只有15个质数,所以可以考虑打表。所以可以考虑预处理方案数对应最小的数字。哦哦,记得开long double。
最后说下dfs中部分变量的意思,mul是当前乘积,sol是当前乘积的方案数。
#include<bits/stdc++.h>
using namespace std;
#define ri register int
#define ll long long
#define double long double
const int N=50;
int n,prime[100005],not_prime[100005],tot;
int now,ans[N];
ll f1[1000005],f2[1000005];
double mx;
double target;
struct info{
double x,y;
}f[1000005];
bool operator <(const info& a,const info& b){
if(a.x==b.x)
return a.y<b.y;
return a.x<b.x;
}
inline void pre(){
for(ri i=2;i<=100;++i){
if(!not_prime[i]) prime[++tot]=i;
for(ri j=1;j<=tot&&prime[j]*i<=100;++j){
not_prime[prime[j]*i]=1;
if(!(i%prime[j])) break;
}
}
}
inline void dfs(int kind,int sum,int up,double sol,double mul){
if(mul>=mx||kind>15)
return;
for(ri i=1;i<=up;++i){
mul*=prime[kind];
sol=sol*(sum+i)/i;//这里就是推的结论
if(mul>mx||sol>mx)
return;
f[++tot].x=sol;
f[tot].y=mul;
dfs(kind+1,sum+i,i,sol,mul);
}
}
int main(){
pre();
mx=LONG_LONG_MAX;
scanf("%d",&n);
dfs(1,0,63,1,1);
sort(f+1,f+tot+1);
now=0;
for(ri i=1;i<=tot;++i){
if(f[i].x!=f[i-1].x)
f1[++now]=(ll)f[i].x,f2[now]=(ll)f[i].y;
}
while(n--){
ll k;
scanf("%lld",&k);
int pos=lower_bound(f1+1,f1+now+1,k)-f1;
printf("%lld\n",f2[pos]);
}
return 0;
}