给定n,m,min和max,求所有的<i,j>,满足0<=i<=n,0<=j<=m并且min<=i*j<=max。
要求:不得使用暴力法,算法复杂度要求O(n,m)<nlogm并且O(n,m)<mlogn。提示:
1.设有k和l,若满足k*l<min,对于i<=k且j<=l,则<i,j>是不满足条件的;若k*l>max,对于i>=k且j>=l,则<i,j>是不满足条件的。
2.可以考虑用三分法。
3.需要考虑n和m比较小的情形,例如0,1,2,也许需要做特殊的处理。
样例数据如下:
输入:n,m,min和max分别为10,10,31,41
结果:
<4 8>
<4 9>
<4 10>
<5 7>
<5 8>
<6 6>
<7 5>
<8 4>
<8 5>
<9 4>
<10 4>
暴力法程序如下:
/* B00015 平方矩阵问题(暴力法) */
#include <iostream>
using namespace std;
int main()
{
int n, m, mins, maxs;
scanf("%d%d%d%d", &n, &m, &mins, &maxs);
for(int i=0; i<=n; i++)
for(int j=0; j<=m; j++) {
if(mins <= i * j && i * j <= maxs)
printf("<%d %d>\n", i, j);
}
return 0;
}
运行结果(输入与输出):
10 10 31 41
<4 8>
<4 9>
<4 10>
<5 7>
<5 8>
<6 6>
<7 5>
<8 4>
<8 5>
<9 4>
<10 4>
根据网友提供的程序改进后的程序:
/* B00015 平方矩阵问题(二分法) */
#include <iostream>
#include <stdio.h>
using namespace std;
int b_search_max(int row, int left, int right , int maxs)
{
int mid;
while(left <= right) {
mid = (left + right) / 2;
if(row * mid > maxs)
right = mid - 1;
else if(row * mid < maxs)
left = mid + 1;
else { // ==
left = mid;
break;
}
}
return right;
}
int b_search_min(int row, int left, int right , int mins)
{
int mid;
while(left <= right) {
mid = (left + right) / 2;
if(row * mid < mins)
left = mid + 1;
else if(row * mid > mins)
right = mid - 1;
else { // ==
left = mid;
break;
}
}
return left;
}
int main()
{
int n, m, mins, maxs;
int bot, top;
scanf("%d%d%d%d", &n, &m, &mins, &maxs);
for(int i=0; i<=n; i++) {
top = b_search_max(i, 0, m, maxs);
bot = b_search_min(i, 0, top, mins);
for(int j = bot; j <= top; j++)
printf("<%d %d>\n", i, j);
}
return 0;
}
运行结果(输入与输出)之一:
10 10 31 41
<4 8>
<4 9>
<4 10>
<5 7>
<5 8>
<6 6>
<7 5>
<8 4>
<8 5>
<9 4>
<10 4>
运行结果(输入与输出)之二:
15 15 31 41
<3 11>
<3 12>
<3 13>
<4 8>
<4 9>
<4 10>
<5 7>
<5 8>
<6 6>
<7 5>
<8 4>
<8 5>
<9 4>
<10 4>
<11 3>
<12 3>
<13 3>
进一步改进后的程序:
/* B00015 平方矩阵问题(综合二分法) */
#include <iostream>
#include <stdio.h>
using namespace std;
int b_search_max(int row, int left, int right , int maxs)
{
int mid;
while(left <= right) {
mid = (left + right) / 2;
if(row * mid > maxs)
right = mid - 1;
else if(row * mid < maxs)
left = mid + 1;
else { // ==
left = mid;
break;
}
}
return right;
}
int b_search_min(int row, int left, int right , int mins)
{
int mid;
while(left <= right) {
mid = (left + right) / 2;
if(row * mid < mins)
left = mid + 1;
else if(row * mid > mins)
right = mid - 1;
else { // ==
left = mid;
break;
}
}
return left;
}
int main()
{
int n, m, mins, maxs;
int bot, top;
scanf("%d%d%d%d", &n, &m, &mins, &maxs);
int minrow = b_search_min(m, 0, n, mins);
int maxcol = b_search_max(minrow, 0, m, maxs);
int mincol = b_search_min(n, 0, maxcol, mins);
int maxrow = b_search_max(mincol, minrow, n, maxs);
for(int i=minrow; i<=maxrow; i++) {
top = b_search_max(i, mincol, maxcol, maxs);
bot = b_search_min(i, mincol, top, mins);
for(int j = bot; j <= top; j++)
printf("<%d %d>\n", i, j);
}
return 0;
}
运行结果(输入与输出)之一:
10 10 31 41
<4 8>
<4 9>
<4 10>
<5 7>
<5 8>
<6 6>
<7 5>
<8 4>
<8 5>
<9 4>
<10 4>
运行结果(输入与输出)之二:
15 15 31 41
<3 11>
<3 12>
<3 13>
<4 8>
<4 9>
<4 10>
<5 7>
<5 8>
<6 6>
<7 5>
<8 4>
<8 5>
<9 4>
<10 4>
<11 3>
<12 3>
<13 3>