Ural 1748. The Most Complex Number DFS+反素数

本文探讨了如何在指定范围内找到具有最多除数的整数,并详细解释了反素数特性及其应用。

1748. The Most Complex Number

Time limit: 1.0 second
Memory limit: 64 MB
Let us define a complexity of an integer as the number of its divisors. Your task is to find the most complex integer in range from 1 to n. If there are many such integers, you should find the minimal one.

Input

The first line contains the number of testcases t (1 ≤ t ≤ 100). The i-th of the following t lines contains one integer ni (1 ≤ ni ≤ 1018).

Output

For each testcase output the answer on a separate line. The i-th line should contain the most complex integer in range from 1 to ni and its complexity, separated with space.

Sample

input output
5
1
10
100
1000
10000
1 1
6 4
60 12
840 32
7560 64
Problem Author: Petr Lezhankin
Problem Source: Ufa SATU Contest. Petrozavodsk Summer Session, August 2009
求n范围内约数个数最多的那个数。
反素数第一点:g(x)表示 x含有因子的数目,设 0<i<=x 则g(i)<=x;
反素数第二个特性:2^t1*3^t2^5^t3*7^t4..... 这里有 t1>=t2>=t3>=t4...
^t1*3^t2*5^t3*...p1^x***p2^y,假设p1是大于prime[]中所有的素数的,因为这几个素数的乘积大于10^16,如果我们添加p1在这个连乘积式子里面,那么必然有至少一个prime[i]不在这个连乘积式子里面,但是对于因子的总数目而言我们在乎的是幂的大小,而非素因子的大小,也就是说如果素因子越大,反而会使因子的数目偏小。
#include<stdio.h>
#include <string.h>
int const maxSize=55;
int prime[maxSize];     //保存筛得的素数
int primeSize;          //保存的素数的个数
bool isPrime[maxSize+1];
void init()//素数筛法
{
    //#include <cstring>
    //初始化,所有数字均没被标记
    memset(isPrime,true,sizeof(isPrime));
    isPrime[0]=isPrime[1]=false;
    primeSize = 0; //得到的素数个数为0
    //依次遍历2到maxSize所有数字
    for (int  i=2; i<= maxSize; i++)
    {
        //若该数字已经被标记,则跳过
        if(!isPrime[i]) continue;
        //否则,又新得到一个新素数
        prime[primeSize++]=i;
        //并将该数的所有倍数均标记成非素数
        for (int  j=i*i; j<=maxSize &&j>=0; j+=i)
        {
            isPrime[j]=false;
        }
    }
}
long long maxA,maxR;

void dfs(int u,int Limit,long long res,long long ret,long long ans)
{
    if(ans>maxA||ans==maxA&&ret<maxR)
    {
        maxA=ans;
        maxR=ret;
    }
    if((u>=15)||(res<prime[u]))
        return;
    for(long long i=prime[u],si=1; i<=res&&si<=Limit; i*=prime[u],si++)
        dfs(u+1,si,res/i,ret*i,ans*(si+1));
}
int main()
{
    init();
    int ncase;
    long long n;
    while(scanf("%d",&ncase)!=EOF)
    {
        while(ncase--)
        {
            scanf("%I64d",&n);
            maxA=0;
            dfs(0,64,n,1,1);
            printf("%I64d %I64d\n",maxR,maxA);
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值