标签:次方 https ios 个数 clu 分解 bool 更新 int
求区间[L,R]内约数个数最多的数和它的约数个数。
这个题吧,乍一看确实不是很难,然后稍微一想,嗯,是个傻*题。这是唯一感受,不要问我为什么。
首先我们定义一个函数\(F(X)\)表示\(X\)的约数个数。题目要求求出\([L,R]\)中的\(F(X)max\)和这个数。首先最基本我们要知道每一个数\(Data[i]\)都一个基本性质:
\(Data[i] = Prime_1^{M_1} \times Prime_2^{M_2} \times ... \times Prime_N^{M_N}\),语言表示就是任意i一个数都可以分解成多个质数的若干次方的乘积,稍微搞一搞我们得到\(F(X) = (M_1 + 1) \times (M_2 + 1) \times ...\times (M_N + 1)\)。
由此将搜索的过程由质因数分解转化为了质因数相乘,则搜索的时候只需要搜索质因数就可以了,然后记录质因数的个数即可。当然,单纯这样搞是会\(T\)掉的,下面数一下剪枝:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std ;
typedef long long LL ;
const int MAXN = 500010 ;
const int MAXM = 40000 ;
int L, R, Ans, Max, Prime[MAXN] ;
bool NotP[MAXN] ; int Tot ;
inline void Dfs(LL H, LL N, LL Now) {
if (H > Tot || N > R) return ;
int K = (int)(log(R / double(N)) / log(double(Prime[H]))) ;
if (Now * (1 << K) < Ans) return ;
if (N >= L && (Now > Ans || (Now == Ans && N < Max)))
Ans = Now, Max = N ;
LL X = 1 ;
for (int i = 1 ; i <= K ; i ++) X *= Prime[H] ;
for (int i = K + 1 ; i >= 1 ; i --) {
Dfs(H + 1, N * X, Now * i) ;
X /= Prime[H] ;
} return ;
}
int main() {
scanf("%d %d", & L, & R) ;
if (L == R && L == 1) {
printf("Between %d and %d, 1 has a maximum of 1 divisors.\n", L, R);
return 0 ;
}
for (int i = 2 ; i <= MAXM ; i ++) {
if (! NotP[i]) {
Prime[++ Tot] = i ;
for (int j = i << 1 ; j <= MAXM ; j += i)
NotP[j] = true ;
}
}
if (R - L <= 10000) {
for (int i = L ; i <= R ; i ++) {
int T = 2 ;
for (int j = 2 ; j * j <= i ; j ++) {
if (j * j == i) T ++ ;
else if (i % j == 0) T += 2 ;
} if (T > Ans) Ans = T, Max = i ;
}
}
else Dfs(1, 1, 1) ;
printf("Between %d and %d, %d has a maximum of %d divisors.\n", L, R, Max,Ans);
return 0 ;
}
标签:次方 https ios 个数 clu 分解 bool 更新 int
原文地址:https://www.cnblogs.com/Yeasio-Nein/p/P1221.html