牛客网练习赛14

这篇博客详细解析了牛客网竞赛中的三道题目:A题求在一定范围内约数个数最多的数的约数个数,使用了约数个数定理和正整数唯一分解定理;E题为无向图最短距离问题,通过BFS和位运算优化解决了多源最短路径问题;B题涉及区间连续段划分,利用倍增法预处理求解。
摘要由CSDN通过智能技术生成

A-约数个数

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

输入描述:

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

输出描述:

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

解析

我知道要用到约数个数定理,但是写出的代码还是超时了,因为还有一个重要的定理即正整数唯一分解定理,即任意一个大于1的自然数都可以分解成质数的积,到这里还不算什么。重要的是求约数个数最大多的,那么应该发现这样的事实,就是低质因子的幂越高,对应的约数个数就越多。你想啊,一个数乘以2肯定比乘以5递增的慢把,这样就能产生更多的约数。

X = p_1^a*p_2^b*....p_n^n

s.t. \space p_1 \geq p_2 ....\geq p_n

s.t. \space a \geq b .... \geq n 

所以我们的目标即是上式子,即尽可能使低质数的幂次要高些,同时后面的质数的幂次小于等于前面。因为如果存在低质数的幂次小于高质数的幂次(假设此时约数个数为n),那么这个数的范围内,必然存在低质数的幂次高于高质数的幂次也可以使约数个数为n,故同等效果,这里这样强制,为了就是减少不必要的计算

代码
package com.special.test14;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.StringTokenizer;

/**
 * Create by Special on 2018/4/6 14:22
 */
public class ProA {
   

    static int[] prime = {
  2,3,5,7,11,13,17,19,23,29,31,37,41,43,47};
    static long n, max;
    static int limit = 18; 

    /**
     *
     * @param num 当前数的大小
     * @param sum 当前数的约数个数
     * @param limit 上一个质因子的幂次
     * @param index 考虑到哪个质数了
     */
    static void dfs(long num, long sum, int limit, int index){
        max = Math.max(max, sum);
        if(index == 15) { return; } //多往后考虑几个质数也无碍吗,万一最大约数的质因子种类很多呢
        long tmp = n / prime[index];
        for(int i = 1; i <= limit; i++){
            if(num <= tmp) { //当前的质数还可以往上乘,则继续
                num *= prime[index];
                dfs(num,sum * (i + 1), i, index + 1);
            }
        }
    }

    public static void main(String[] args){
        FastScanner input = new FastScanner();
        PrintWriter out = new PrintWriter(System.out);
        int t = input.nextInt();
        while(t-- > 0){
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值