二分-四平方和

洛谷原题链接
原理:如果使用三层循环的方式遍历答案时间复杂度O(N^3)过高可能超时,所以选择使用二分的方式:首先两层循环遍历c,d的所有可能性,并将其存入集合中,并根据c×c+d×d对集合元素排序,然后二层循环从小到大遍历所有a,b的可能性,并对每种可能性二分查找有没有与之对应的c,d,若有则直接输出该a,b,c,d即为字典序最小的情况,使用二分后可将时间复杂度降低至O(N^2logn)

import java.util.*;

class SUM{
    int c;
    int d;
    int sum;
    public SUM(int c,int d,int sum) {
        this.c = c;
        this.d = d;
        this.sum = sum;
    }
}
public class Main{
    static int N = 5000000;
    public static void main(String args[]){
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        List<SUM> list = new ArrayList();
        for(int c = 0;c * c < N;c ++)
            for(int d = c;c * c + d * d < N; d++) {
                SUM sum = new SUM(c,d,c * c + d * d);
                list.add(sum);
            }
        list.sort(new Comparator<SUM>() {
            @Override
            public int compare(SUM o1, SUM o2) {
                if (o1.sum != o2.sum) return o1.sum - o2.sum;
                if (o1.c != o2.c) return o1.c - o2.c;
                return o1.d - o2.d;
            }
        });
        for(int a = 0;a * a < N;a ++)
            for(int b = a;a * a + b * b < N; b ++) {
                int cd = n - a * a - b * b;
                int l = 0,r = list.size() - 1;
                while(l < r) {
                	int mid = (l + r) / 2;
                	if(list.get(mid).sum >= cd) {
                		r = mid;
                	}else {
                		l = mid + 1;
                	}
                }
                if(list.get(r).sum == cd) {
                	System.out.println(a+" "+b+" "+list.get(r).c+" "+list.get(r).d);
                	return;
                }
            }
        scan.close();
    }
}

你可能感兴趣的:(算法,java,算法,数据结构)