题目大意:
定义一个数 n 的复杂度(complexity) 为其因子的个数,现在给出一个n,求不大于n的所有正整数中复杂度最大的整数,如果有多个,求最小的那个
要求输出那个整数和它的复杂度
大致思路:
这道题的话,首先要明白的就是由于数 n <= 10^18 ; 但是为了使得因子的数量多,在不超过n的前提下,拥有同样多因子的数,如果其质因数组成更小,则组成的数应该就更小,
那么我们可以将质因数进行分层
第 i 层是第 i 个质数,这一层是有多个选择的,即 乘上 多少次第 i 个质数都是不同的分支。
这样每次向下递推,每次向下走都至少乘上一个质数(可以明显的知道跳过某层是不优于不跳过的)
这样每次向下递归到一个值的时候都更新一下之前的答案。
递归时注意到反素数在越深层取的数越少可以再dfs的时候用lim来限制进行剪枝。
代码如下:
Result : Accepted Memory : 329 KB Time : 281 ms
/* * Author: Gatevin * Created Time: 2014/7/24 18:59:43 * File Name: test.cpp */ #include<iostream> #include<sstream> #include<fstream> #include<vector> #include<list> #include<deque> #include<queue> #include<stack> #include<map> #include<set> #include<bitset> #include<algorithm> #include<cstdio> #include<cstdlib> #include<cstring> #include<cctype> #include<cmath> #include<ctime> #include<iomanip> using namespace std; const double eps(1e-8); typedef long long lint; lint n,t; lint maxx,cnt; lint prime[50]; bool check[100]; void dfs(lint now, lint num, lint pri, lint lim) { if(cnt < num || (num == cnt && now < maxx)) { maxx = now; cnt = num; } lint y = prime[pri]; for(lint i = 1; i <= lim; i++) { if(n/y < now) break; now *= y; dfs(now, num*(i + 1), pri + 1, i); } } int main() { memset(check, 0, sizeof(check)); int tot = 0; for(lint i = 2; i <= 100; i++) { if(!check[i]) prime[tot++] = i; for(lint j = 2*i; j < 100; j += i) { check[j] = 1; } } scanf("%I64d",&t); while(t--) { scanf("%I64d",&n); maxx = 1; cnt = 1; dfs(1,1,0,64); printf("%I64d %I64d\n",maxx,cnt); } return 0; }