做这道题得自己推出这么几个结论……
1.最大的反素数一定是约数个数最多的的数中最小的那个。
这个其实很好想:根据定义,g(x)要大于任意的g(i),而不是大于等于。
2.1~n中任意一个数的不同的质因子不会超过10个,且所有质因子的指数之和不会大于30.
最小的10个质数的乘积刚好大于231了,而231 > 2 * 109。
3.把x分解质因数:x = 2a1 * 3a2 * 5a3 * 7a4 * …… * 29a10,一定满足a1 >= a2 >= a3 >= …… >= a10.
证明用反证法。假设x中有一项pk(p > 29),那么=根据第二条结论,前10个质数中一定有一个p'不能整除x,那么我们应该用p'代替p,因为这即保证了约数相等,新的数又更小。
知道这几条结论后,一波爆搜就行了。
(爆搜我写的特别丑,是在不行了再看我的吧)


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 }