做这道题得自己推出这么几个结论……
1.最大的反素数一定是约数个数最多的的数中最小的那个。
这个其实很好想:根据定义,$g(x)$要大于任意的$g(i)$,而不是大于等于。
2.1~n中任意一个数的不同的质因子不会超过10个,且所有质因子的指数之和不会大于30.
最小的10个质数的乘积刚好大于$2^{31}$了,而$2^{31} > 2 * 10^9$。
3.把$x$分解质因数:$x = 2^{a_1} * 3^{a_2} * 5^{a_3} * 7^{a_4} * …… * 29^{a_{10}}$,一定满足$a_1 leqslant a_2 leqslant a_3 leqslant …… leqslant a_{10}$.
证明用反证法。假设$x$中有一项$p_k(p > 29)$,那么根据第二条结论,前10个质数中一定有一个$p'$不能整除$x$,那么我们应该用$p'$代替$p$,因为这即保证了约数相等,新的数又更小。
而之所以递减,是因为如果$x$有相邻的两项$p_i ^ {a_i}, p_j ^ {a_j}(p_i < p_j, a_i > a_j)$,那么完全可以构造出另一个数$x'$,其中两项为$p_i ^ {a_j}, p_j ^{a_i}$,根据算数基本定理,$x$和$x'$约数个数相等,但是$x'$更小,所以应该选$x'$。
知道这几条结论后,一波爆搜就行了。
(爆搜我写的特别丑,是在不行了再看我的吧)
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cctype> 8 #include<stack> 9 #include<queue> 10 #include<vector> 11 using namespace std; 12 #define enter puts("") 13 #define space putchar(' ') 14 #define Mem(a, x) memset(a, x, sizeof(a)) 15 #define rg register 16 typedef long long ll; 17 typedef double db; 18 const int INF = 0x3f3f3f3f; 19 const db eps = 1e-8; 20 //const int maxn = ; 21 inline ll read() 22 { 23 ll ans = 0; 24 char ch = getchar(), las = ' '; 25 while(!isdigit(ch)) las = ch, ch = getchar(); 26 while(isdigit(ch)) ans = ans * 10 + ch - '0', ch = getchar(); 27 if(las == '-') ans = -ans; 28 return ans; 29 } 30 inline void write(ll x) 31 { 32 if(x < 0) putchar('-'), x = -x; 33 if(x >= 10) write(x / 10); 34 putchar(x % 10 + '0'); 35 } 36 37 ll n; 38 const int a[] = {0, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29}; //num = 10 39 ll ans1 = 0, ans = (ll)INF * (ll)INF; 40 41 void dfs(ll now, int id, int sum, int Max, int tot, ll x) 42 { 43 if(!tot || now > n || id > 11) return; 44 if(x > ans1 ||(x == ans1 && now < ans)) ans1 = x, ans = now; 45 ll tp = 1; 46 for(int i = 1; i <= min(tot, Max); ++i) 47 { 48 tp *= a[id]; 49 if(tp > n) break; 50 dfs(now * tp, id + 1, sum + i, i, tot - i, x * (i + 1)); 51 } 52 } 53 54 int main() 55 { 56 n = read(); 57 dfs(1, 1, 0, INF, 30, 1); 58 write(ans); 59 return 0; 60 }