牛客想开了大赛二--n的约数(求在[1,n]内约数个数最多的数的约数个数)

本文探讨了一种高效算法,用于找出指定范围内拥有最多约数的数,并详细解释了其背后的数学原理与质数指数组合策略。通过递归深度优先搜索的方法,实现了对大范围数据的有效处理。

传送们

题意

给定一个t

接下来t行

每行给一个n,求[1,n]中的约数最多的数的约数

输入格式

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

输出格式

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

输入

5
13
9
1
13
16

输出

6
4
1
6
6

数据范围

1=<n=1e18

思路

这道题刚刚看到数据范围的时候,就知道不能够暴力,也没有想到其他想法,就在网上看了题解。

大题思路是这样:

对于每一个数n,我们可以把它分解成这种形式

n=p1a1*p2a2*…pn^an

pi都是质数,这里的pi>pi-1.

那么n的约数就是`(a1+1)(a2+1)(a3+1)

我们知道这个定理后可以做什么呢?

和[1,n]有什么关系呢?

上面的这个定理说明我们只要有质数,再任意组合他们的指数,就可以凑出所有的数。

所以现在的思路就是用指数凑出小于n的数,再更新答案

code


    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    
    int p[20] = {0, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 51};
    
    ll ans, n;
    
    void dfs(int pos, ll num, ll sum, int len)
    {
    	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;
    		dfs(pos + 1, num * (i + 1), sum * (res), i);
    	}
    }
    int main()
    {
        int t,n;
        while(t--)
        {
    	cin >> n;
    	ans = 0;
    	dfs(1, 1, 1, 20);
    	cout << ans << endl;
        }
        return 0;
    
    }



评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值