Divide and conquer:Matrix(POJ 3685)

           

                矩阵

  题目大意:矩阵里面的元素按i*i + 100000 * i + j*j - 100000 * j + i*j填充(i是行,j是列),求最小的M个数

  这一题要用到两次二分,实在是二分法的经典,主要是每一列都是按照行来递增的,每一行我们都用二分法找到比mid小的那些数就好了

  参考http://blog.csdn.net/nw4869/article/details/24124019

  

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <functional>
 4 
 5 using namespace std;
 6 typedef long long LL_INT;
 7 
 8 LL_INT getnum(LL_INT, LL_INT);
 9 bool judge(LL_INT, LL_INT, const int);
10 
11 int main(void)//这题双二分法
12 {
13     int test_sums, size;
14     LL_INT M;
15     scanf("%d", &test_sums);
16 
17     while (test_sums--)
18     {
19         scanf("%d%lld", &size, &M);
20         LL_INT lb = -0x3fffffffffffffff, rb = 0x3fffffffffffffff, mid;
21         while (rb - lb > 1)
22         {
23             mid = (lb + rb) / 2;
24             if (judge(mid, M, size)) lb = mid;
25             else rb = mid;
26         }
27         printf("%lld
", rb);
28     }
29     return 0;
30 }
31 
32 LL_INT getnum(LL_INT i, LL_INT j)
33 {
34     return  i*i + 100000 * i + j*j - 100000 * j + i*j;//注意这题的每一列都是递增的!
35 }
36 
37 bool judge(LL_INT x, LL_INT M, const int N)
38 {
39     LL_INT line_l, line_r, mid, sum = 0;
40     for (int col = 1; col <= N; col++)
41     {
42         line_l = 1; line_r = N + 1;
43         if (getnum(N, col) <= x)//先判断一下这个,还可以剪枝,而且还能避免判断n=1的时候的错误
44             sum += N;
45         else
46         {
47             while (line_r - line_l > 1)
48             {
49                 mid = (line_l + line_r) / 2;
50                 if (getnum(mid, col) <= x) line_l = mid;
51                 else line_r = mid;
52             }
53             if (getnum(line_l, col) <= x)
54                 sum += line_l;
55             else
56                 sum += line_l - 1;
57         }
58     }
59     return sum < M;
60 }

  

原文地址:https://www.cnblogs.com/Philip-Tell-Truth/p/5140879.html