牛客想开了大赛2——B

原题题址

 

题目描述

t次询问,每次给你一个数n,求在[1,n]内约数个数最多的数的约数个数

输入描述:

第一行一个正整数t
之后t行,每行一个正整数n

输出描述:

输出t行,每行一个整数,表示答案

示例1

输入

                                                                                                                                                                                     

5
13
9
1
13
16

输出

                                                                                                                                                                                  

6
4
1
6
6

备注:

对于100%的数据,t <= 500 , 1 <= n <= 1000000000000000000

 关于这个题的思想与方法,其中有两点比较重要,我先给出:

1)较小的质因数的越多越好。

2)质因数的求解不是直接去寻找,而是通过平时知道该用的时候不知道的定理——约数个数定理。

约数个数定理:

若N满足    N = p_{1}^{a_{1}}+p_{2}^{a_{2}}+...+p_{n}^{a_n},就有N的约数个数为(a_{1}+1)(a_{2}+1)...(a_{n}+1)

有了这个本题最重要的两个就很容易得到:

1)明显de:当   \prod_{i=1}^{n}(a_{i}+1)的值恒定时,约数个数不变,但i取较小值a_{i}值较大时,N的值越小。那么反过来,N的值一定时,但i取较小值a_{i}值较大时,约数个数越多。

2)在求解约数个数时:通过控制约数对应的a_{i}的大小关系,排除许多不可能的方案,并在通过公式最终得到答案;

上面说了,通过控制约数对应的a_{i}的大小关系可以排除许多不可能的方案,且询问数较少,搜索变成一种可能。

所以用dfs。

搜索之前,用一个倍数素数筛筛一下素数(类似贪心的策略使素数不可能过大,也可以直接手动打表

素数筛

//比较简单没有写成函数
int a[109],cnt;
bool p[109];
for(int i=2;i<100;i++){
        if(!p[i]){
            a[cnt++]=i;
            for(int j=i;j<100;j+=i)p[j]=1;
}

 搜索的代码(虽说代码简单,只是递归搜索,但其中值的考究的东西还很多)

这个代码相对好懂,直接可以看出过程

void dfs(int pos,ll num,ll sum,int len)//当前枚举p的位置,约数个数,数sum,前一个质因子的指数最大值
{
    if (sum>n) return ;
    if (sum<=n) ans=max(ans,num);
    for (int i=1;i<=len;i++) { 
        ll res=pow(p[pos],i); 
        if (sum>n/res) break;//注意不要用sum*res>n,炸long long 
        dfs(pos+1,num*(i+1),sum*(res),i);
    } 
}

这段代码更难懂,但它充分利用了递归的性质,将上面代码一些重复的步骤省略了

int dfs(ll x,int t,int ci){分别代表当前的数值,素数的表素数的位置,上一个素数的指数值
    int num=1;
    int ans=1;
    while(x/=a[t]){
        ++num;
        if(num>ci)break;
		ans=max(ans,num*dfs(x,t+1,num)) 
        cout <

 最后就整个主函数输入输出

int main(){
    int T;
    cin >> T;
    while(T--){
        cin >> n;
        cout << dfs();//视个人的dfs函数情况填写参数
    }
    return 0;
}

说实话吧,这题我写了半天就憋出了个小型素数表,方向大致有,贪心策略也明白,当时这个定理没想起来,找约数就没好的思路,这题要是约数定理热热乎乎的,没准能整出来,但是做题的时候硬是没想起来,还是不熟练,思路不开阔。

 

 

 

你可能感兴趣的:(牛客想开了大赛2——B)