目录
P5735 【深基7.例1】距离函数
P5736 【深基7.例2】质数筛
P5737 【深基7.例3】闰年展示
P5738 【深基7.例4】歌唱比赛
P5739 【深基7.例7】计算阶乘
P5461 赦免战俘
方法一
方法二
P5740 【深基7.例9】最厉害的学生
方法一
方法二
P5741 【深基7.例10】旗鼓相当的对手 - 加强版
P5742 【深基7.例11】评等级
P1075 [NOIP2012 普及组] 质因数分解
P1304 哥德巴赫猜想
P1217 [USACO1.5] 回文质数 Prime Palindromes
P2415 集合求和
P5743 【深基7.习8】猴子吃桃
P5744 【深基7.习9】培训
P5735 【深基7.例1】距离函数
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
double x1 = sc.nextDouble();
double y1 = sc.nextDouble();
double x2 = sc.nextDouble();
double y2 = sc.nextDouble();
double x3 = sc.nextDouble();
double y3 = sc.nextDouble();
double c = distance(x1,y1,x2,y2) + distance(x1,y1,x3,y3) + distance(x2,y2,x3,y3);
System.out.printf("%.2f",c);
}
public static double distance(double x1,double y1,double x2,double y2){
return Math.sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
}
}
P5736 【深基7.例2】质数筛
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
StringBuilder c = new StringBuilder();
for(int i = 0 ;i < a ;i++){
int b = sc.nextInt();
if(pri(b))
c.append(b).append(" ");
}
System.out.print(c);
}
public static boolean pri(int x){
if(x == 1)
return false;
else{
if(x % 2 != 0 || x == 2) {
for (int i = 3; i <= Math.sqrt(x); i += 2) {
if (x % i == 0)
return false;
}
return true;
}
}
return false;
}
}
经典判断质数,不再赘述了,这里用的是拼接字符串
append()用于拼接字符串,原方法签名如下:
public StringBuilder append(String str) 返回值是拼接后的StringBuilder所以可以链式编程
P5737 【深基7.例3】闰年展示
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int x = sc.nextInt();
int y = sc.nextInt();
int a = 0;
String str = "";
for(;x<=y;x++){
if(x%400 == 0 || (x%4 == 0 && x%100!= 0)){
a++;
str = str+x+" ";
}
}
System.out.println(a);
System.out.println(str.trim()); //删除字符串的头尾空白符
}
}
经典闰年判断,不再赘述
str.trim() 用于删除字符串的头尾空白符
P5738 【深基7.例4】歌唱比赛
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
int b = sc.nextInt();
double score = 0; //最高平均分
for(int i = 0 ;i<a;i++){
int s = 0; //sum——总分
int m = 0; //max——最高分
int n = 10; //min——最低分
for(int k = 0;k<b;k++){
int c = sc.nextInt(); //当前打分
s +=c;
if(c<n)
n = c;
if(c>m)
m = c;
}
double s1 = (s-m-n)/(b-2.0); //当前平均分
if(s1 > score)
score = s1;
}
System.out.printf("%.2f",score);
}
}
P5739 【深基7.例7】计算阶乘
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println(fac(sc.nextInt()));
}
public static int fac(int x){
if(x != 1)
return x*fac(x-1);
else
return 1;
}
}
两种解法,常规解法就是利用循环迭代,另一种就是上面代码展示的递归
循环的思路就不说了,下面说一下递归的思路:
递归简单来说就是自己调用自己,最重要的是脱离递归的条件,不然就容易死循环。
阶乘就是从1乘到这个数本身,每次加一,那我们不妨逆向思维一下,从这个数本身出发,每次减一,直到等于1的时候跳出递归
如下图:
fac(1)的值是1,上一层的fac(2)就可以得到 2*1 = 2 ,fac(3)同理 ...
这样就可以得到阶乘啦~
P5461 赦免战俘
方法一
//方法一
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
int b = (int)Math.pow(2,a);
boolean[][] ans = new boolean[b][b];
ans[0][b-1] = true;
for(int c = 0;c<a;c++){
int diff = 1;
for(int i = 0;i<2;i++){
for(int m = 0;m<(int)Math.pow(2,c);m++){
int d = (int) Math.pow(2, c);
System.arraycopy(ans[d - 1 - m], b - d, ans[d*2 - 1 - m], b - (d*2 / diff), d);
//等第一处全部拷贝完成后,再去拷贝第二处
}
diff = 2;
}
}
for(int i = 0 ;i<b;i++){
for(int k = 0;k<b;k++){
if(ans[i][k])
System.out.print("1 ");
else
System.out.print("0 ");
}
System.out.println();
}
}
}
具体思路如下:
从右上角开始向下进行两次复制,依次循环,如图:
这是第一次复制 把1复制到下一行的两个
这是第二次复制,以此类推 ...
System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
src:源数组;
srcPos:源数组要复制的起始位置;
dest:目的数组;
destPos:目的数组放置的起始位置;
length:复制的长度.
System.arraycopy(ans[d - 1 - m], b - d, ans[d*2 - 1 - m], b - (d*2 / diff), d);
这句就是这个程序的核心步骤,将d-1-m是起始块的最后一行(-1因为索引从0开始),之后随着m++,逐渐到起始块的第一行,而d*2-1-m是目标块的最后一行,这样就能做将原数组复制到目标块中
b-(d*2/diff)当diff = 1时,目标块为第一块,diff = 2时 目标块为第二块
方法二
import java.util.Arrays;
import java.util.Scanner;
public class Main {
//改良版,比原版快0.7s左右
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = (int)Math.pow(2,sc.nextInt());
int[][] a = {{0, 1}, {1, 1}};
int[][] d = d(a, n);
for (int[] ints : d) {
System.out.println(Arrays.toString(ints).substring(1, n * 3-1).replaceAll(", "," "));
/*
不加substring 和 replaceAll 的结果是下面这样的:
[0, 0, 0, 1]
[0, 0, 1, 1]
[0, 1, 0, 1]
[1, 1, 1, 1]
*/
}
}
private static int[][] d(int[][] a, double n) {
if (n != a.length) {
int c = a.length*2;//4
int t = a.length;//2
int [][] b = new int[c][c];//[4][4]
for (int i = 0; i < t; i++) {
System.arraycopy(a[i], 0, b[i], t, c - t);
}
for (int i = t; i < c; i++) {
for (int j = 0; j < c; j++) {
b[i][j] = a[i-t][j%t];
}
}
return d(b,n);
}else {
return a;
}
}
}
这个也是一个递归思想,当原数组的大小已经拓展到了整个数组的时候跳出递归。
大家可以带一个数进去试一下,便于理解
这两个方法其实思路差不多,都是利用数组复制来解决问题
P5740 【深基7.例9】最厉害的学生
方法一
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
score[] ss = new score[a];
for(int i = 0;i<a;i++) {
String name = sc.next();
int s1 = sc.nextInt();
int s2 = sc.nextInt();
int s3 = sc.nextInt();
score s = new score(name,s1,s2,s3);
ss[i] = s;
}
Arrays.sort(ss);
System.out.println(ss[0].toString());
}
}
class score implements Comparable<score> {
private String name;
private int sum;
private int s1;
private int s2;
private int s3;
public score(String name, int s1, int s2, int s3) {
this.name = name;
this.sum = s1+s2+s3;
this.s1 = s1;
this.s2 = s2;
this.s3 = s3;
}
@Override
public int compareTo(score o) {
return Integer.compare(o.sum, this.sum);
}
@Override
public String toString() {
return name+" "+s1+" "+s2+" "+s3;
}
}
这里为了方便操作,直接把数据存成对象,再实现接口里面的比较方法compareTo,就可以指定比较规则了
数字的比较大小直接可以用compare,或者自己写规则也可以
常用的对象比较都会实现这个接口,大家可以记忆一下
Arrays.sort 底层就是靠这个方法实现的
//Arrays.sort() 底层源代码
public static void sort(Object[] a) {
if (LegacyMergeSort.userRequested)
legacyMergeSort(a);
else
ComparableTimSort.sort(a, 0, a.length, null, 0, 0);
}
private static void legacyMergeSort(Object[] a) {
Object[] aux = a.clone();
mergeSort(aux, a, 0, a.length, 0);
}
private static void mergeSort(Object[] src,
Object[] dest,
int low,
int high,
int off) {
int length = high - low;
// Insertion sort on smallest arrays
if (length < INSERTIONSORT_THRESHOLD) {
for (int i=low; i<high; i++)
for (int j=i; j>low &&
((Comparable) dest[j-1]).compareTo(dest[j])>0; j--)
//在这里调用的compareTo
swap(dest, j, j-1);
return;
}
方法二
import java.util.*;
public class Main {
//优化代码,只记录最高的成绩及名字
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
int n = s.nextInt();
String name = "";
int a,b,c,sum = -1;
int ans1 = 0,ans2 = 0,ans3 = 0;
String ans = "";
for (int i = 0; i < n; i++) {
name = s.next();
a = s.nextInt();
b = s.nextInt();
c = s.nextInt();;
if(sum<(a+b+c)) {
sum = a + b + c;
ans = name;
ans1 = a;ans2 = b;ans3 = c;
}
}
System.out.println(ans+" "+ans1+" "+ ans2+" "+ans3);
}
}
这个方法不使用结构体,直接进行比较
P5741 【深基7.例10】旗鼓相当的对手 - 加强版
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
Score[] ss = new Score[n];
for (int i = 0; i < n; i++) {
String str = sc.next();
int s1 = sc.nextInt();
int s2 = sc.nextInt();
int s3 = sc.nextInt();
ss[i] = new Score(str, s1, s2, s3);
}
for (int i = 0; i < n - 1; i++) {
for (int k = i + 1; k < n; k++) {
ss[i].compare(ss[k]);
}
}
}
}
class Score {
private String name;
private int s1, s2, s3, sum;
public Score(String name, int s1, int s2, int s3) {
this.s1 = s1;
this.s2 = s2;
this.s3 = s3;
this.name = name;
this.sum = s1 + s2 + s3;
}
public void compare(Score o) {
if (Math.abs(this.sum - o.sum) <= 10) {
if (Math.abs(this.s1 - o.s1) <= 5 && Math.abs(this.s2 - o.s2) <= 5 && Math.abs(this.s3 - o.s3) <= 5)
System.out.println(this.name + " " + o.name);
}
}
}
这题就是自定义比较规则
因为没有用Arrays.sort() 所以不用重写compareTo
P5742 【深基7.例11】评等级
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
Score[] ss = new Score[n];
for (int i = 0; i < n; i++) {
sc.nextInt();
int s2 = sc.nextInt();
int s3 = sc.nextInt();
ss[i] = new Score(s2, s3);
compare(ss[i]);
}
}
public static void compare(Score a) {
if (a.syn() >= 800 && a.sum > 140)
System.out.println("Excellent");
else
System.out.println("Not excellent");
}
}
class Score {
int s2, s3, sum;
public Score(int s2, int s3) {
this.s2 = s2;
this.s3 = s3;
this.sum = s2 + s3;
}
public int syn() {
return this.s2 * 7 + this.s3 * 3;
}
}
P1075 [NOIP2012 普及组] 质因数分解
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
int b = 2;
for(int i = 1;2*i+1<Math.sqrt(a);i++){
if(a%b==0){
break;
}
b = 2*i+1;
}
System.out.println(Math.max(b, a / b));
}
}
此题在循环结构那章出现过,不再赘述
P1304 哥德巴赫猜想
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int b = sc.nextInt();
for(int i = 4;i<=b;i+=2){
for(int k = 2;k<=i/2;k++){
if(Ispri(k) &&Ispri(i-k) ){
System.out.printf("%d=%d+%d\n",i,k,i-k);
break;
}
}
}
}
public static boolean Ispri(int a){
for (int i = 2; i <= Math.sqrt(a); i++) {
if (a % i == 0)
return false;
}
return true;
}
}
Ispri用来判断是否是质数
主函数第一个for用来输出4~N的偶数
第二个for用来找满足条件的最小质数
P1217 [USACO1.5] 回文质数 Prime Palindromes
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
int b = sc.nextInt();
int pa = 0;
String sb = String.valueOf(b);
int bl = sb.length();
for(int i = 1;i<=bl;i++) {
switch (i) {
case 1:
//质数一定不是二的倍数,简化掉以2的倍数结尾的数
for (int a1 = 1; a1 <= 9; a1 += 2) {
pa = a1;
if (pa >= a && pa <= b && zhishu(pa))
System.out.println(pa);
}
break;
case 2:
for (int a1 = 1; a1 <= 9; a1 += 2) {
pa = a1 * 10 + a1;
if (pa >= a && pa <= b && zhishu(pa))
System.out.println(pa);
}
break;
case 3:
for (int a1 = 1; a1 <= 9; a1 += 2) {
for (int b1 = 0; b1 <= 9; b1++) {
pa = a1 * 100 + b1 * 10 + a1;
if (pa >= a && pa <= b && zhishu(pa))
System.out.println(pa);
}
}
break;
// case 4:
// for (int a1 = 1; a1 <= 9; a1 += 2) {
// for (int b1 = 0; b1 <= 9; b1++) {
// pa = a1 * 1000 + b1 * 100 + b1 * 10 + a1;
// if (pa >= a && pa <= b && zhishu(pa))
// System.out.println(pa);
// }
// }
// break;
//偶数次回文数没有质数,除11外
case 5:
for (int a1 = 1; a1 <= 9; a1 += 2) {
for (int b1 = 0; b1 <= 9; b1++) {
for (int c1 = 0; c1 <= 9; c1++) {
pa = a1 * 10000 + b1 * 1000 + c1 * 100 + b1 * 10 + a1;
if (pa >= a && pa <= b && zhishu(pa))
System.out.println(pa);
}
}
}
break;
case 6:
for (int a1 = 1; a1 <= 9; a1 += 2) {
for (int b1 = 0; b1 <= 9; b1++) {
for (int c1 = 0; c1 <= 9; c1++) {
pa = a1 * 100000 + b1 * 10000 + c1 * 1000 + c1*100+ b1 * 10 + a1;
if (pa >= a && pa <= b && zhishu(pa))
System.out.println(pa);
}
}
}
break;
case 7:
for (int a1 = 1; a1 <= 9; a1 += 2) {
for (int b1 = 0; b1 <= 9; b1++) {
for (int c1 = 0; c1 <= 9; c1++) {
for(int d1 = 0;d1<=9;d1++) {
pa = a1 * 1000000 + b1 * 100000 + c1 * 10000+ d1*1000+ c1 * 100 + b1 * 10 + a1;
if (pa >= a && pa <= b && zhishu(pa))
System.out.println(pa);
}
}
}
}
break;
case 8:
for (int a1 = 1; a1 <= 9; a1 += 2) {
for (int b1 = 0; b1 <= 9; b1++) {
for (int c1 = 0; c1 <= 9; c1++) {
for(int d1 = 0;d1<=9;d1++) {
pa = a1 * 10000000 + b1 * 1000000 + c1 * 100000+ d1*10000 +d1*1000+ c1 * 100 + b1 * 10 + a1;
if (pa >= a && pa <= b && zhishu(pa))
System.out.println(pa);
}
}
}
}
break;
// case 9:
// for (int a1 = 1; a1 <= 9; a1 += 2) {
// for (int b1 = 0; b1 <= 9; b1++) {
// for (int c1 = 0; c1 <= 9; c1++) {
// for(int d1 = 0;d1<=9;d1++) {
// for(int e1 = 0;e1<=9;e1++) {
// pa = a1 * 100000000 + b1 * 10000000 + c1 * 1000000 + d1 * 100000+e1*10000 + d1 * 1000 + c1 * 100 + b1 * 10 + a1;
// if (pa >= a && pa <= b && zhishu(pa))
// System.out.println(pa);
// }
// }
// }
// }
// }
// break;
//一亿并不是回文数,也不是质数
}
}
}
static boolean zhishu(int a){
if(a<5)
return false;
for(int b = 2;b <= Math.sqrt(a);b++){
if( a % b == 0)
return false;
}
return true;
}
}
同样在循环结构那章出现过
P2415 集合求和
import java.util.*;
public class Main {
public static void main(String[] args) {
long sum = 0;
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
String[] ss = s.split(" ");
for(int i = 0;i<ss.length;i++){
int num = Integer.parseInt(ss[i]);
sum += num * Math.pow(2,ss.length-1);
}
System.out.println(sum);
}
}
这题用int会超范围!!!!!用long或者高精度
集合的真子集数为 2^n - 1 n --> 集合中元素个数
所有子集中,元素出现次数 2^(n-1)
所以直接用各项*2^(n-1)再求和就可以了
P5743 【深基7.习8】猴子吃桃
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
System.out.println(Monkey(n,1));
}
public static int Monkey(int a,int b){
b = (b+1)*2;
if(a==1)
return 1;
if(a==2)
return b;
return Monkey(--a,b);
}
}
因为这个b = (b+1)*2在判断的上面,所以在a==2的时候就已经增加过了,直接ruturn b就可以 了
a==1是有可能买回来就只有一个,这种情况直接return 1;就可以
P5744 【深基7.习9】培训
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
sc.nextLine();
String[][] str = new String[n][3];
for(int i = 0; i<n;i++){
String s = sc.nextLine();
str[i] = s.split(" ");
str[i][1] = String.valueOf(Integer.parseInt(str[i][1])+1);
str[i][2] = String.valueOf(Math.min(Integer.parseInt(str[i][2]) * 12 / 10, 600));
String ss = Arrays.toString(str[i]);
//eg:ss中的数据如下 [kkksc03, 25, 0]
ss = ss.replaceAll(", "," "); //去掉逗号
System.out.println(ss.substring(1,ss.length()-1));//截去中括号
}
}
}
Integer.parseInt()将字符串转为整形
String.valueOf()将内容转为字符串