<—点个赞吧QwQ
宣传一下算法提高课整理{:target=”_blank”}
对于任何正整数 x,其约数的个数记作 g(x),例如 g(1)=1、g(6)=4。
如果某个正整数 x 满足:对于任意的小于 x 的正整数 i,都有 g(x)>g(i),则称 x 为反素数。
例如,整数 1,2,4,6 等都是反素数。
现在给定一个数 N,请求出不超过 N 的最大的反素数。
输入格式
一个正整数 N。
输出格式
一个整数,表示不超过 N 的最大反素数。
数据范围
1leNle2\*109
输入样例:
1000
输出样例:
840
思路
假设[1,n]中约数个数最多的数的约数个数为s。
则对于[1,n]中所有数,满足约数个数是s的所有数当中,反素数是这些数中最小的那个。
反证法:假设存在约数个数为s的两个数a,b,且a>b,则g(a)≤g(b),但a>b,矛盾。因此反素数必定是这些数中最小的那个。
得到上属性之后,继续分析:
- 对于数据范围[1,2×109],因为2×3×5×7×9×11×13×17×19×23×29>2×109,所以满足不同银子相乘的最大质数为23
- 对数范围[1,2×109],因为231>2×109,所以能够满足质因子的最大次数为30
- 对于数据范围[1,2×109],质因子从小到大,其次数必定是不单调上升的。
反证法:假设存在两个质因子a,b,且满足a>b,a,b的次数分别记作ka,kb,且ka>kb
则对于反素数x=⋯aka⋅bkb⋯,必然存在数x′<x
而根据我们推到的第一个性质,x′更有可能是所求的反素数,而并非x,故矛盾。
接下来,我们整理下我们的条件:
- 质因子数量不单调递增
- 质因子最大枚举到23
- 单个质因子次数最多为30
代码
#include <iostream>
using namespace std;
typedef long long LL;
int n;
int primes[] = {2,3,5,7,11,13,17,19,23};
int ans,maxd;
void dfs (int u,int last,int num,int sum) {
if (sum > maxd || (sum == maxd && num < ans)) maxd = sum,ans = num;
if (u == 9) return ;
for (int i = 1;i <= last;i++) {
if ((LL)num * primes[u] > n) return ;
num *= primes[u];
dfs (u + 1,i,num,sum * (i + 1));
}
}
int main () {
cin >> n;
dfs (0,30,1,1);
cout << ans << endl;
return 0;
}
非严格单调递减 : 原来我叫不单调递增
“不同银子”(银子-》因子)
那个应该是打错了,应该是不同银子,打成了不同银子hh~