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){