AcWing 1221. 四平方和
题意:拉格朗日定理,每个正整数都可以表示为至多 4 个正整数(包括零)的平方和。求出这四个数
这题归在二分里,但是二分的做法没太看懂。。也可以用哈希表来做,为了简化算法可以将算式转化为c2+d2=n−a2−b2 ,将四重循环简化成两个两重,通过哈希表来存储值,如果c2+d2在哈希表key中存在,则算式成立。
import java.io.*;
import java.util.*;
public class Main {
static Scanner tab = new Scanner(System.in);
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
static int N = 100010;
public static void main(String[] args) throws IOException {
Map<Integer,Integer> map=new HashMap<>();
int n=tab.nextInt();
//遍历出ab,乘积存储在哈希表key中,a存储在value中
for(int i=0;i*i<=n;i++) {
for(int j=i;j*j+i*i<=n;j++) {
if(!map.containsKey(i*i+j*j)) {
map.put(i*i+j*j, i);
}
}
}
//遍历出cd
for(int i=0;i*i<=n;i++) {
for(int j=i;j*j+i*i<=n;j++) {
int k=n-i*i-j*j;
if(map.containsKey(k)) {
int c=map.get(k);
int d=(int)Math.sqrt(k-c*c);
System.out.println(i + " " + j + " " + c + " " + d);
return ;
}
}
}
}
}
常规代码如上,可以在for循环判别条件中增加限定条件简化时间,例如求a时ii2<=n同样可以达到效果,具体原因不在赘述,不过这题中常规写法也可以通过,代码更明了一点
AcWing 1227. 分巧克力
题意:n块巧克力分给k个人,每块巧克力分别有长宽,要求每人分到的巧克力都是正方形且大小相等,求可分的正方形巧克力最大边长
典型二分题,找到巧克力中最短的短边min,从1到min进行二分,对每个值进行check,直至最大值就可,注意mid边界问题
import java.io.*;
import java.util.*;
public class Main {
static Scanner tab = new Scanner(System.in);
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
static int N = 100010;
static int n,k;
static cholo c[]=new cholo[N];
static class cholo{
int x;//长边
int y;
public cholo(int x, int y) {
super();
if(x<y) {
//使用宽值
int t=x;
x=y;
y=t;
}
this.x = x;
this.y = y;
}
}
public static boolean check(int t) {
int sum=0;
for(int i=0;i<n;i++) {
int x=c[i].x/t;
int y=c[i].y/t;
sum+=x*y;
}
if(sum>=k)
return true;
return false;
}
static public int find(int l,int r) {
if(l==r) {
return l;
}
int mid=(l+r+1)/2;//取右+1
if(check(mid)) {
return find(mid,r);
}
else
return find(l,mid-1);
}
public static void main(String[] args) throws IOException {
n=tab.nextInt();
k=tab.nextInt();
int max=0;
for(int i=0;i<n;i++) {
c[i]=new cholo(tab.nextInt(),tab.nextInt());
if(c[i].y>max)
max=c[i].y;
}
int k=find(1,max);
System.out.println(k);
}
}
二分题一般思路比较清晰,主要需要注意的点在于二分对象的选择、函数跳出处理和mid的取值
关于判断是否要使用二分可以考虑元素的二分性和单调性,即当一个值满足某条件时其前或其后的值都能满足条件,或是元素序列单调递增递减,当满足这种情况时就可以考虑使用二分来避免使用遍历造成的大量时间浪费,具体性质可以参考y总的视频,不再赘述