2017 CCPC秦皇岛 G题 Numbers
DreamGrid has a nonnegative integer . He would like to divide into nonnegative integers and minimizes their bitwise or (i.e. and should be as small as possible).
Input
There are multiple test cases. The first line of input contains an integer , indicating the number of test cases. For each test case:
The first line contains two integers and ().
It is guaranteed that the sum of the length of does not exceed .
<h4< dd="">Output
For each test case, output an integer denoting the minimum value of their bitwise or.
<h4< dd="">Sample Input
5 3 1 3 2 3 3 10000 5 1244 10
<h4< dd="">Sample Output
3 3 1 2000 125
题解:题意很简单,就是让你把n分成m份,然后让你求这m份按位或的最小值;(注意数据范围,大数模板考虑下Orz)
考虑一个k满足m*2^k <= n < m*2^(k+1)如果使得结果最小,则对于分开后,每个数的最高位(二进制)位置越小,找到一个k后,我们让这m个数字第k位都为一。
然后剩下n-m*2^k(相当于新的n),递归求解即可;
参考代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 // base and base_digits must be consistent 4 constexpr int base = 1000000000; 5 constexpr int base_digits = 9; 6 struct bigint 7 { 8 vector<int> z; 9 int sign; 10 bigint() : sign(1) {} 11 bigint(long long v) 12 { 13 *this = v; 14 } 15 bigint& operator=(long long v) 16 { 17 sign = v < 0 ? -1 : 1; 18 v *= sign; 19 z.clear(); 20 for(; v > 0; v = v / base) z.push_back((int)(v % base)); 21 return *this; 22 } 23 24 bigint(const string& s) 25 { 26 read(s); 27 } 28 29 bigint& operator+=(const bigint& other) 30 { 31 if (sign == other.sign) 32 { 33 for (int i = 0, carry = 0; i < other.z.size() || carry; ++i) 34 { 35 if(i == z.size()) z.push_back(0); 36 z[i] += carry + (i < other.z.size() ? other.z[i] : 0); 37 carry = z[i] >= base; 38 if(carry) z[i] -= base; 39 } 40 } 41 else if (other != 0 /* prevent infinite loop */) 42 { 43 *this -= -other; 44 } 45 return *this; 46 } 47 48 friend bigint operator+(bigint a, const bigint& b) 49 { 50 return a += b; 51 } 52 53 bigint& operator-=(const bigint& other) 54 { 55 if (sign == other.sign) 56 { 57 if (sign == 1 && *this >= other || sign == -1 && *this <= other) 58 { 59 for (int i = 0, carry = 0; i < other.z.size() || carry; ++i) 60 { 61 z[i] -= carry + (i < other.z.size() ? other.z[i] : 0); 62 carry = z[i] < 0; 63 if(carry) z[i] += base; 64 } 65 trim(); 66 } 67 else 68 { 69 *this = other - *this; 70 this->sign = -this->sign; 71 } 72 } 73 else *this += -other; 74 return *this; 75 } 76 77 friend bigint operator - (bigint a, const bigint& b) 78 { 79 return a -= b; 80 } 81 82 bigint& operator*=(int v) 83 { 84 if(v < 0) sign = -sign, v = -v; 85 for(int i = 0, carry = 0; i < z.size() || carry; ++i) 86 { 87 if(i == z.size()) z.push_back(0); 88 long long cur = (long long)z[i] * v + carry; 89 carry = (int)(cur / base); 90 z[i] = (int)(cur % base); 91 } 92 trim(); 93 return *this; 94 } 95 96 bigint operator*(int v) const 97 { 98 return bigint(*this) *= v; 99 } 100 101 friend pair<bigint, bigint> divmod(const bigint& a1, const bigint& b1) 102 { 103 int norm = base / (b1.z.back() + 1); 104 bigint a = a1.abs() * norm; 105 bigint b = b1.abs() * norm; 106 bigint q, r; 107 q.z.resize(a.z.size()); 108 109 for (int i = (int)a.z.size() - 1; i >= 0; i--) 110 { 111 r *= base; 112 r += a.z[i]; 113 int s1 = b.z.size() < r.z.size() ? r.z[b.z.size()] : 0; 114 int s2 = b.z.size() - 1 < r.z.size() ? r.z[b.z.size() - 1] : 0; 115 int d = (int)(((long long)s1 * base + s2) / b.z.back()); 116 r -= b * d; 117 while(r < 0) r += b, --d; 118 q.z[i] = d; 119 } 120 121 q.sign = a1.sign * b1.sign; 122 r.sign = a1.sign; 123 q.trim(); 124 r.trim(); 125 return {q, r / norm}; 126 } 127 128 friend bigint sqrt(const bigint& a1) 129 { 130 bigint a = a1; 131 while(a.z.empty() || a.z.size() % 2 == 1) a.z.push_back(0); 132 133 int n = a.z.size(); 134 int firstDigit = (int)::sqrt((double)a.z[n - 1] * base + a.z[n - 2]); 135 int norm = base / (firstDigit + 1); 136 a *= norm; 137 a *= norm; 138 while(a.z.empty() || a.z.size() % 2 == 1) a.z.push_back(0); 139 140 bigint r = (long long)a.z[n - 1] * base + a.z[n - 2]; 141 firstDigit = (int)::sqrt((double)a.z[n - 1] * base + a.z[n - 2]); 142 int q = firstDigit; 143 bigint res; 144 for (int j = n / 2 - 1; j >= 0; j--) 145 { 146 for(;; --q) 147 { 148 bigint r1 = (r - (res * 2 * base + q) * q) * base * base + (j > 0 ? (long long)a.z[2 * j - 1] * base + a.z[2 * j - 2] : 0); 149 if(r1 >= 0) 150 { 151 r = r1; 152 break; 153 } 154 } 155 res *= base; 156 res += q; 157 if(j > 0) 158 { 159 int d1 = res.z.size() + 2 < r.z.size() ? r.z[res.z.size() + 2] : 0; 160 int d2 = res.z.size() + 1 < r.z.size() ? r.z[res.z.size() + 1] : 0; 161 int d3 = res.z.size() < r.z.size() ? r.z[res.z.size()] : 0; 162 q = (int)(((long long)d1 * base * base + (long long)d2 * base + d3) / (firstDigit * 2)); 163 } 164 } 165 166 res.trim(); 167 return res / norm; 168 } 169 170 bigint operator/(const bigint& v) const 171 { 172 return divmod(*this, v).first; 173 } 174 175 bigint operator%(const bigint& v) const 176 { 177 return divmod(*this, v).second; 178 } 179 180 bigint& operator/=(int v) 181 { 182 if(v < 0) sign = -sign, v = -v; 183 for (int i = (int)z.size() - 1, rem = 0; i >= 0; --i) 184 { 185 long long cur = z[i] + rem * (long long)base; 186 z[i] = (int)(cur / v); 187 rem = (int)(cur % v); 188 } 189 trim(); 190 return *this; 191 } 192 193 bigint operator/(int v) const 194 { 195 return bigint(*this) /= v; 196 } 197 198 int operator%(int v) const 199 { 200 if(v < 0) v = -v; 201 int m = 0; 202 for(int i = (int)z.size() - 1; i >= 0; --i) m = (int)((z[i] + m * (long long)base) % v); 203 return m * sign; 204 } 205 206 bigint& operator*=(const bigint& v) 207 { 208 *this = *this * v; 209 return *this; 210 } 211 212 bigint& operator/=(const bigint& v) 213 { 214 *this = *this / v; 215 return *this; 216 } 217 218 bool operator<(const bigint& v) const 219 { 220 if(sign != v.sign) return sign < v.sign; 221 if(z.size() != v.z.size()) return z.size() * sign < v.z.size() * v.sign; 222 for(int i = (int)z.size() - 1; i >= 0; i--) 223 if(z[i] != v.z[i]) return z[i] * sign < v.z[i] * sign; 224 return false; 225 } 226 227 bool operator>(const bigint& v) const 228 { 229 return v < *this; 230 } 231 bool operator<=(const bigint& v) const 232 { 233 return !(v < *this); 234 } 235 bool operator>=(const bigint& v) const 236 { 237 return !(*this < v); 238 } 239 bool operator==(const bigint& v) const 240 { 241 return !(*this < v) && !(v < *this); 242 } 243 bool operator!=(const bigint& v) const 244 { 245 return *this < v || v < *this; 246 } 247 248 void trim() 249 { 250 while(!z.empty() && z.back() == 0) z.pop_back(); 251 if(z.empty()) sign = 1; 252 } 253 254 bool isZero() const 255 { 256 return z.empty(); 257 } 258 259 friend bigint operator-(bigint v) 260 { 261 if(!v.z.empty()) v.sign = -v.sign; 262 return v; 263 } 264 265 bigint abs() const 266 { 267 return sign == 1 ? *this : -*this; 268 } 269 270 long long longValue() const 271 { 272 long long res = 0; 273 for(int i = (int)z.size() - 1; i >= 0; i--) res = res * base + z[i]; 274 return res * sign; 275 } 276 277 friend bigint gcd(const bigint& a, const bigint& b) 278 { 279 return b.isZero() ? a : gcd(b, a % b); 280 } 281 282 friend bigint lcm(const bigint& a, const bigint& b) 283 { 284 return a / gcd(a, b) * b; 285 } 286 287 void read(const string& s) 288 { 289 sign = 1; 290 z.clear(); 291 int pos = 0; 292 while(pos < s.size() && (s[pos] == '-' || s[pos] == '+')) 293 { 294 if(s[pos] == '-') sign = -sign; 295 ++pos; 296 } 297 for(int i = (int)s.size() - 1; i >= pos; i -= base_digits) 298 { 299 int x = 0; 300 for(int j = max(pos, i - base_digits + 1); j <= i; j++) x = x * 10 + s[j] - '0'; 301 z.push_back(x); 302 } 303 trim(); 304 } 305 306 friend istream& operator>>(istream& stream, bigint& v) 307 { 308 string s; 309 stream >> s; 310 v.read(s); 311 return stream; 312 } 313 314 friend ostream& operator<<(ostream& stream, const bigint& v) 315 { 316 if(v.sign == -1) stream << '-'; 317 stream << (v.z.empty() ? 0 : v.z.back()); 318 for(int i = (int)v.z.size() - 2; i >= 0; --i) 319 stream << setw(base_digits) << setfill('0') << v.z[i]; 320 return stream; 321 } 322 323 static vector<int> convert_base(const vector<int>& a, int old_digits, int new_digits) 324 { 325 vector<long long> p(max(old_digits, new_digits) + 1); 326 p[0] = 1; 327 for(int i = 1; i < p.size(); i++) p[i] = p[i - 1] * 10; 328 vector<int> res; 329 long long cur = 0; 330 int cur_digits = 0; 331 for(int v : a) 332 { 333 cur += v * p[cur_digits]; 334 cur_digits += old_digits; 335 while (cur_digits >= new_digits) 336 { 337 res.push_back(int(cur % p[new_digits])); 338 cur /= p[new_digits]; 339 cur_digits -= new_digits; 340 } 341 } 342 res.push_back((int)cur); 343 while(!res.empty() && res.back() == 0) 344 res.pop_back(); 345 return res; 346 } 347 348 typedef vector<long long> vll; 349 static vll karatsubaMultiply(const vll& a, const vll& b) 350 { 351 int n = a.size(); 352 vll res(n + n); 353 if(n <= 32) 354 { 355 for (int i = 0; i < n; i++) 356 for (int j = 0; j < n; j++) 357 res[i + j] += a[i] * b[j]; 358 return res; 359 } 360 361 int k = n >> 1; 362 vll a1(a.begin(), a.begin() + k); 363 vll a2(a.begin() + k, a.end()); 364 vll b1(b.begin(), b.begin() + k); 365 vll b2(b.begin() + k, b.end()); 366 vll a1b1 = karatsubaMultiply(a1, b1); 367 vll a2b2 = karatsubaMultiply(a2, b2); 368 for(int i = 0; i < k; i++) a2[i] += a1[i]; 369 for(int i = 0; i < k; i++) b2[i] += b1[i]; 370 371 vll r = karatsubaMultiply(a2, b2); 372 for(int i = 0; i < a1b1.size(); i++) r[i] -= a1b1[i]; 373 for(int i = 0; i < a2b2.size(); i++) r[i] -= a2b2[i]; 374 for(int i = 0; i < r.size(); i++) res[i + k] += r[i]; 375 for(int i = 0; i < a1b1.size(); i++) res[i] += a1b1[i]; 376 for(int i = 0; i < a2b2.size(); i++) res[i + n] += a2b2[i]; 377 return res; 378 } 379 380 bigint operator*(const bigint& v) const 381 { 382 vector<int> a6 = convert_base(this->z, base_digits, 6); 383 vector<int> b6 = convert_base(v.z, base_digits, 6); 384 vll a(a6.begin(), a6.end()); 385 vll b(b6.begin(), b6.end()); 386 while(a.size() < b.size()) a.push_back(0); 387 while(b.size() < a.size()) b.push_back(0); 388 while(a.size() & (a.size() - 1)) a.push_back(0), b.push_back(0); 389 vll c = karatsubaMultiply(a, b); 390 bigint res; 391 res.sign = sign * v.sign; 392 for (int i = 0, carry = 0; i < c.size(); i++) 393 { 394 long long cur = c[i] + carry; 395 res.z.push_back((int)(cur % 1000000)); 396 carry = (int)(cur / 1000000); 397 } 398 res.z = convert_base(res.z, 6, base_digits); 399 res.trim(); 400 return res; 401 } 402 }; 403 /*********************************************** 404 上面为大数模板 核心代码 405 ************************************************/ 406 int main() 407 { 408 ios::sync_with_stdio(0); 409 cin.tie(0); 410 bigint n, m; 411 int T; 412 cin >> T; 413 while(T--) 414 { 415 cin >> n >> m; 416 bigint ans = 0; 417 bigint now = 1; 418 while(now<= n) 419 { 420 now = now * 2; 421 } 422 while(n != 0) 423 { 424 while(now != 1 && now * m > n) 425 { 426 now = now / 2; 427 } 428 if((now * 2 - 1) * m < n) 429 now = now * 2; 430 bigint num = n / now; 431 if(num > m) 432 num = m; 433 n = n - num * now; 434 ans = ans + now; 435 } 436 cout << ans << endl; 437 } 438 return 0; 439 } 440