Matrix POJ3685

投稿日: 更新日:

問題:http://poj.org/problem?id=3685

問題

N×NN\times Nの行列AAがあります。ii行目jj列目をAijA_{ij}としたとき、その値はi2+100000×i+j2100000×j+i×ji^2+100000\times i + j^2 - 100000\times j + i\times jに等しいです。整数MMが与えられるので、MM番目に小さい値を出力してください。

解法

AijvA_{ij} \leqq vとなる値がMM個以上か、で二分探索します。

AijA_{ij}の値はjjを固定した際、iiについて単調増加です。よって、各jjに対し二分探索でiiの個数を数えて行けば良いです。

実装

#include <iostream>
using namespace std;

long long calc(long long i, long long j){
    return i*i + 100000*i + j*j - 100000*j + i*j;
}

void solve(){
    int n;
    long long m;
    cin >> n >> m;
    long long ok = 1e18, ng = -1e18;
    while(ok-ng > 1){
        long long v = (ok+ng)/2;

        long long count = 0;
        for(int j = 1;j <= n; ++j){
            int ok = 0, ng = n+1;
            while(ng - ok > 1){
                int mid = (ok+ng)/2;
                if(calc(mid, j) <= v){
                    ok = mid;
                }else{
                    ng = mid;
                }
            }
            count += ok;
        }

        if(count >= m){
            ok = v;
        }else{
            ng = v;
        }
    }
    cout << ok << endl;
}

int main(){
    int t;
    cin >> t;
    while(t--){
        solve();
    }
}

書いた人

profile_image

お茶の葉

物理とプログラミングが好きな人