• 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>
    ", 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>
    ", 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>
    ", 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>

      



  • 相关阅读:
    事件处理之跨浏览器
    IE事件处理
    DOM0级事件处理、DOM2级事件处理
    JS内置对象学习总结
    JS事件响应的学习总结
    vuex的学习例子
    npm run build 打包后,如何运行在本地查看效果(Apache服务)
    Vue.js 引入外部js方法
    Table展开行
    正则表达式test()和exec()、 search() 和 replace()用法实例
  • 原文地址:https://www.cnblogs.com/tigerisland/p/7563542.html
Copyright © 2020-2023  润新知