Description
一天,小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向你求助。
Input
第一行,一个整数T。
接下来的T行,每行一个整数k。
Output
T行,每行一个整数,其中第i行的整数表示第i个k值对应的n的值。
Sample Input
4
1
2
3
105
Sample Output
2
6
12
720
Data Constraint
对于30%的数据,1< n<=100000;
对于全部的数据,1< n<2^63,1< k<2^63,1<=T<=1000。
Solution
考虑
x=p1a1×p2a2×…×pnan它的质因子排列方式一共有:
(a1+a2+…+an)!a1!∗a2!∗...∗an!因此可以得出最终回答的数的形式一定是这样的:
2a1×3a2×5a3×7a4×…其中 a1≥a2≥a3≥a4…
我们可以搜索出所有符合这样要求的数和对应的排列方案数,
然后建一个map(C++)或者有序表,然后查询。(范围内符合条件的数一共19274个)。
为避免各种问题,我开的是 long double 和 unsigned long long 。
提示:质数最多为15个(从 2 到 47 为止)。
Code
#include<cstdio>
#include<algorithm>
#include<cctype>
using namespace std;
typedef unsigned long long ULL;
typedef long double LDB;
const int N=1e5+1;
const ULL inf=(1ULL<<63)-1;
struct data
{
ULL x,y;
}f[N];
ULL f1[N],f2[N];
int tot,tot1,h[16];
bool bz[50];
template<typename T>inline T read()
{
T X=0,w=0; char ch=0;
while(!isdigit(ch)) w|=ch=='-',ch=getchar();
while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
return w?-X:X;
}
void dfs(int x,int y,int z,LDB s1,LDB s2)
{
if(x>15) return;
for(int i=1;i<=z;i++)
{
s1*=(LDB)h[x];
if(s1>inf) return;
s2=s2*(LDB)(y+i)/i;
if(s2>inf) return;
f[++tot].x=s2;
f[tot].y=s1;
dfs(x+1,y+i,i,s1,s2);
}
}
inline bool cmp(data x,data y)
{
return x.x<y.x || x.x==y.x && x.y<y.y;
}
int main()
{
for(int i=2;i<=47;i++)
{
if(!bz[i]) h[++h[0]]=i;
for(int j=1;j<=h[0] && i*h[j]<=47;j++)
{
bz[i*h[j]]=true;
if(i%h[j]==0) break;
}
}
dfs(1,0,63,1,1);
sort(f+1,f+1+tot,cmp);
for(int i=1;i<=tot;i++)
if(f[i].x!=f[i-1].x) f2[++tot1]=f[i].x,f1[tot1]=f[i].y;
int T=read<int>();
while(T--)
{
ULL k=read<ULL>();
int x=lower_bound(f2+1,f2+1+tot1,k)-f2;
printf("%llu\n",f1[x]);
}
return 0;
}