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。
题解
如果一个数
X=ap11∗ap22∗...∗apnn
那么它的排列方式就要:
(p1+p2+...+pn)!p1!+p2!+...+pn!
因为要求的数最小,所以在同一种方案数中
一定是
p1≥p2≥...≥pn
最优,
而且可以发现真正的质因数很少不到20个,
而且在满足上述条件,且不≥
263
的数不多。
所以先所有的数预处理出来,存在一个数组里面,排好序,
询问的时候就直接二分出答案。
code
#include<queue>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include <cstring>
#include <string.h>
#include <cmath>
#include <math.h>
#include <time.h>
#include <map>
#define ll long long
#define N 100003
#define M 103
#define db double
#define P putchar
#define G getchar
#define zz 9223372036854775807
#define mo 2147483647
using namespace std;
char ch;
void read(ll &n)
{
n=0;
ch=G();
while((ch<'0' || ch>'9') && ch!='-')ch=G();
ll w=1;
if(ch=='-')w=-1,ch=G();
while('0'<=ch && ch<='9')n=(n<<3)+(n<<1)+ch-'0',ch=G();
n*=w;
}
int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}
ll abs(ll x){return x<0?-x:x;}
ll sqr(ll x){return x*x;}
void write(ll x){if(x>9) write(x/10);P(x%10+'0');}
int ss[19]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67},tot,l,r,mid;
ll k,T,s[19][80],mx[19],C[80][80];
struct node
{
ll x,y;
}w[200000];
bool cmp(node a,node b)
{
return a.y<b.y || (a.y==b.y && a.x<b.x);
}
void dg(int x,int lst,ll S,ll sum,int p)
{
if(x>18)return;
tot++;
w[tot].x=S;
w[tot].y=sum;
//t[S]=sum;
//t.insert(std::pair<ll,ll>(S,sum));
//printf("%d : %d %d %lld %lld %d\n",tot,x,lst,S,sum,p);
lst=min(lst,mx[x]);
for(int i=lst;i;i--)
if(S<=zz/s[x][i] && (C[p+i+1][i+1]!=0 && sum<=zz/C[p+i+1][i+1]))
dg(x+1,i,S*s[x][i],sum*C[p+i+1][i+1],p+i);
}
int main()
{
for(int i=0;i<19;i++)
for(s[i][0]=1,mx[i]=0;s[i][mx[i]]<=zz/ss[i];mx[i]++)
s[i][mx[i]+1]=s[i][mx[i]]*ss[i];
for(int i=1;i<=80;i++)
{
C[i][i]=C[i][1]=1;
for(int j=2;j<i;j++)
if(C[i-1][j] && C[i-1][j-1])C[i][j]=C[i-1][j]+C[i-1][j-1];
}
dg(0,mx[0],1,1,0);
sort(w+1,w+1+tot,cmp);
freopen("factors.in","r",stdin);
freopen("factors.out","w",stdout);
for(read(T);T;T--)
{
read(k);
if(k==1)
{
P('2');P('\n');
continue;
}
l=1;r=tot;
while(l<r)
{
mid=(l+r)>>1;
if(w[mid].y<k)l=mid+1;else r=mid;
}
write(w[l].x);
P('\n');
}
return 0;
}