BZOJ3085: 反质数加强版SAPGAP
用质因子来表示数
先得到一个最小的$K$满足$2^K>p_i$
由$2^{q_1}{p_i}^{q_i}>2^{q_1+K-1}p_i^{q_i-1}$可以得到
$(q_1+1)\cdot(q_i+1)>(q_1+K)\cdot(q_i)$
整理可得$q_i<\frac{q_1+1}{K-1}$
用类似的方法可以得到$q_1 < 2K-1$
搜索+上面两个剪枝即可通过本题。
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define LL long long 4 struct bign{ 5 int a[30], m; 6 bign(char *s) { 7 m = 1; 8 memset(a, 0, sizeof(a)); 9 int n = strlen(s); 10 for(int i = 0; i < n; ++ i) { 11 if(i) { 12 if((n - i) % 4 == 0) ++ m; 13 } 14 a[m] = a[m] * 10 + s[i] - '0'; 15 } 16 for(int i = 1; i <= m / 2; ++ i) { 17 swap(a[i], a[m - i + 1]); 18 } 19 } 20 bign(int x) { 21 memset(a, 0, sizeof(a)); 22 a[1] = x; m = 1; 23 } 24 bign() { 25 memset(a, 0, sizeof(a)); 26 m = 0; 27 } 28 inline bign operator * (const bign& rhs) const { 29 bign ret = bign(0); 30 ret.m = m + rhs.m - 1; 31 for(int i = 1; i <= m; ++ i) { 32 for(int j = 1; j <= rhs.m; ++ j) { 33 ret.a[i + j - 1] += a[i] * rhs.a[j]; 34 ret.a[i + j] += ret.a[i + j - 1] / 10000; 35 ret.a[i + j - 1] %= 10000; 36 } 37 } 38 if(ret.a[m + rhs.m]) ++ ret.m; 39 return ret; 40 } 41 inline bool operator < (const bign& rhs) const { 42 if(m > rhs.m) return false; 43 if(m < rhs.m) return true; 44 for(int i = m; i >= 1; -- i) { 45 if(a[i] < rhs.a[i]) return true; 46 if(a[i] > rhs.a[i]) return false; 47 } 48 return false; 49 } 50 inline bool operator == (const bign& rhs) const { 51 if(m > rhs.m) return false; 52 if(m < rhs.m) return false; 53 for(int i = m; i >= 1; -- i) { 54 if(a[i] < rhs.a[i]) return false; 55 if(a[i] > rhs.a[i]) return false; 56 } 57 return true; 58 } 59 inline bool operator <= (const bign& rhs) const { 60 return (*this == rhs) || (*this < rhs); 61 } 62 inline void print() { 63 printf("%d", a[m]); 64 for(int i = m - 1; i >= 1; -- i) { 65 printf("%04d", a[i]); 66 } 67 } 68 }; 69 int prime[] = 70 { 71 1, 2, 3, 5, 7, 72 11, 13, 17, 19, 23, 73 29, 31, 37, 41, 43, 74 47, 53, 59, 61, 67, 75 71, 73, 79, 83, 89, 76 97, 101,103,107,109, 77 113,127,131,137,139, 78 149,151,157,163,167, 79 173,179,181,191,193, 80 197,199,211,223,227, 81 229,233,239,241,251 82 }; 83 int K[] = 84 { 85 1,2,2,3,3, 86 4,4,5,5,5, 87 5,5,6,6,6, 88 6,6,6,6,7, 89 7,7,7,7,7, 90 7,7,7,7,7, 91 7,7,8,8,8, 92 8,8,8,8,8, 93 8,8,8,8,8, 94 8,8,8,8,8, 95 8,8,8,8,8 96 }; 97 bign n, Ans; 98 LL mx; 99 char s[110]; 100 int q1; 101 inline void dfs(int x, bign now, LL cnt, int lim) { 102 if(cnt > mx || cnt == mx && now < Ans) { 103 Ans = now; mx = cnt; 104 } 105 if(x != 1) { 106 lim = min(lim, q1 / (K[x] - 1)); 107 } 108 LL tmp = cnt; 109 for(int i = 1; i <= lim; ++ i) { 110 if(x == 1) q1 = i; 111 tmp += cnt; 112 now = now * bign(prime[x]); 113 if(n < now) return; 114 dfs(x + 1, now, tmp, i); 115 } 116 } 117 int main() { 118 scanf("%s", s); 119 n = bign(s); 120 if(n == bign(1)) { 121 return puts("1"), 0; 122 } 123 int k = 0; 124 bign tmp = bign(1); 125 while(tmp <= n) { 126 tmp = tmp * bign(prime[++ k]); 127 } 128 dfs(1, bign(1), 1, 2 * K[k] - 2); 129 Ans.print(); 130 }