JZOJ 3775. 【NOIP2014模拟8.15】因子的排列

12 篇文章 0 订阅
8 篇文章 0 订阅

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×

  • 其中 a1a2a3a4

  • 我们可以搜索出所有符合这样要求的数和对应的排列方案数,

  • 然后建一个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;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值