poj 3685 Matrix (二分套二分)

本文介绍了解决POJ 3685问题的一种经典算法——二分套二分法。该算法通过对表达式的观察确定了在一定条件下原表达式的值与变量i之间的单调性关系,并通过枚举j和二分查找i来统计小于目标值的数量,最终找到符合条件的解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:http://poj.org/problem?id=3685

题意:说的很明确了。

思路:

很经典的二分套二分,通过观察表达式我们可以发现当j一定的时候,原表达式的值是跟i相关并且是单调的,所以我们可以二分答案m,然后统计比m小的数有多少个,在统计的时候需要先枚举j,然后再二分i,统计完成后,还需要判断这个结果是否存在(即是否存在i,j使表达式的值等于m),为此我的做法是在统计<=m的数,如果<=m的数的个数大于<m的数则这个结果是存在的。

整个算法的复杂度是O(n*logn*longn) 这种二分再二分的思路是非常经典的~~~~。

code:

#include <cstdio>
#include <cstdlib>
#include <iostream>
#define INF 10000005000
using namespace std;
typedef long long LL;


LL N,M;

LL cal(LL a,LL b)
{
    return a*a+100000*a+b*b-100000*b+a*b;
}

bool judge(LL k)
{
    LL res=0;
    for(int j=1;j<=N;j++){
        LL st=0,ed=N+1;
        while(ed-st>1){
            LL mid=(st+ed)/2;
            if(cal(mid,j)>=k) ed=mid;
            else st=mid;
        }
        res+=st;
        if(res>=M) return true;
    }
    return false;
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%lld%lld",&N,&M);
        LL s=-(3*N*N+200000*N),t=3*N*N+200000*N;
        while(t-s>1){
            LL mid=(s+t)/2;
            if(judge(mid)) t=mid;
            else{
                s=mid;
            }
        }
        printf("%lld\n",s);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值