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   
View Code

 

posted @ 2018-10-14 20:18  StarHai  阅读(607)  评论(0编辑  收藏  举报