B00015 平方矩阵问题
给定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>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架