洛谷题单:【入门6】函数与结构体

(1)P5735 【深基7.例1】距离函数
求三角形周长,就是把三条边加起来,所以可以写个根据坐标求边长的函数,然后把3次函数求和输出。

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		double x1=sc.nextDouble(),y1=sc.nextDouble(),x2=sc.nextDouble(),y2=sc.nextDouble(),x3=sc.nextDouble(),y3=sc.nextDouble();
		double res=distance(x1,y1,x2,y2)+distance(x1,y1,x3,y3)+distance(x2,y2,x3,y3);
		System.out.println(String.format("%.2f", res));
	}
	public static double distance(double a1,double b1,double a2,double b2) {
		return Math.sqrt((a1-a2)*(a1-a2)+(b1-b2)*(b1-b2));
	}
}

(2)P5736 【深基7.例2】质数筛
从题目就能知道这道题要干什么了,求质数。既然是入门的题,应该可以用最朴素的求素数方法肯定能求出来。但还是练习一下筛法,因为有时候数据量大的时候只能用筛法。我这里用的是埃式筛,等数据量太大的时候,就要用欧拉筛了。

import java.util.Scanner;

public class Main {
	static boolean[] arr=new boolean[100010];
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		prime();
		int n=sc.nextInt();
		for(int i=0;i<n;i++) {
			int x=sc.nextInt();
			if(!arr[x]) {
				System.out.print(x+" ");
			}
		}
	}
	public static void prime() {
        arr[0]=arr[1]=true;
		for(int i=2;i<=100000;i++) {
			if(i*i>100000) {
				break;
			}
			if(!arr[i]) {
				for(int j=i*2;j<=100000;j+=i) {
					arr[j]=true;
				}
			}
		}
	}
}

(3)P5737 【深基7.例3】闰年展示
和上题其实差不多,只是一个是判断闰年,一个是判断质数。这里它不能边判断边输出,因为它要先输出闰年个数,所以用个布尔数组标记下。循环判断下,如果是闰年就标记,最后扫描数组。求闰年的方法就是一个if判断即可。

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int a=sc.nextInt(),b=sc.nextInt();
		int sum=0;
		boolean[] arr=new boolean[3010];
		for(int i=a;i<=b;i++) {
			if(i%4==0&&i%100!=0||i%400==0) {
				sum++;
				arr[i]=true;
			}
		}
		System.out.println(sum);
		for(int i=1582;i<=3000;i++) {
			if(arr[i]) {
				System.out.print(i+" ");
			}
		}
	}
}

(4)P5738 【深基7.例4】歌唱比赛
把每一行的所有分数加起来,再减去这一行的最大值和最小值。用一个变量维护分数的最大值,最后把这个最大值分数的平均分算出。


import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt(),m=sc.nextInt();
		double[] arr=new double[n];
		double maxx=0;
		for(int i=0;i<n;i++) {
			double min=10,max=0,sum=0;
			for(int j=0;j<m;j++) {
				double x=sc.nextDouble();
				sum+=x;
				min=Math.min(min, x);
				max=Math.max(max, x);
			}
			sum-=min+max;
			maxx=Math.max(maxx, sum);
		}
		System.out.print(String.format("%.2f", maxx/(m-2))+" ");
	}
}

(5)P5739 【深基7.例7】计算阶乘
题目规定不能用循环求阶乘,但它不知道我一般都是用递归做的。没啥好说的,就是一只递归然后n-1,等n=1时候返回乘积就好啦。

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		System.out.println(f(n));
	}
	public static int f(int n) {
		if(n==1||n==0) {
			return n;
		}
		return n*f(n-1);
	}
}

(6)P5461 赦免战俘
一道普及/提高-的题目,但其实不算难。只要递归的有一些基础都能想到,先建立一个全是1的二维数组。然后根据坐标和长度进行递归的设置成1,每次把3个剩下的三个小正方形进行递归,知道边长为1无法再递归就停止。但这题如果用Java最后一个测试点是过不了的,因为输出的数据太大了,会超时,这里就要用PintWriter进行快速输出,这样就能通过最后一个测试点。

import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Scanner;

public class Main {
	static int[][] arr;
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
		int m=sc.nextInt(),n=1;
		for(int i=0;i<m;i++) {
			n*=2;
		}
		arr=new int[n][n];
		for(int i=0;i<n;i++) {
			Arrays.fill(arr[i], 1);
		}
		f(n,0,0);
		for(int i=0;i<n;i++) {
			for(int j=0;j<n;j++) {
				out.print(arr[i][j]+" ");
			}
			out.println();
		}
		out.close();
		
	}
	public static void f(int n,int x,int y) {
		if(n==1) {
			return;
		}
		for(int i=x;i<x+n/2;i++) {
			for(int j=y;j<y+n/2;j++) {
				arr[i][j]=0;
			}
		}
		f(n/2,x+n/2,y);
		f(n/2,x,y+n/2);
		f(n/2,x+n/2,y+n/2);
	}
}

(7)P5740 【深基7.例9】最厉害的学生
考察结构体的使用,java没有结构体就要用类来实现了。当然还要写一个自定义排序。相对来说代码比较多,不过关于这种用结构体排序的题目其实做多了,把模板网上套就行。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;

public class Main {
	public static void main(String[] args) throws  IOException {
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		int n=Integer.valueOf(br.readLine());
		p1[] p=new p1[n];
		for(int i=0;i<n;i++) {
			String[] s=br.readLine().split(" ");
			p[i]=new p1(i,s[0],Integer.valueOf(s[1])+Integer.valueOf(s[2])+Integer.valueOf(s[3]),Integer.valueOf(s[1]),Integer.valueOf(s[2]),Integer.valueOf(s[3]));
		}
		Arrays.sort(p);
		System.out.println(p[0].name+" "+p[0].a+" "+p[0].b+" "+p[0].c);
	}
}
class p1 implements Comparable<p1>{
	int id,a,b,c,score;
	String name;
	p1(int id,String name,int score,int aa,int bb,int cc){
		this.id=id;this.name=name;this.score=score;
		a=aa;b=bb;c=cc;
	}
	@Override
	public int compareTo(p1 o) {
		if(score==o.score) return id-o.id;
		return o.score-score;
	}
}

(8)P5741 【深基7.例10】旗鼓相当的对手 - 加强版
这道题在数组那个题单里做过,这次是加强版。因为这道题要用结构体存数据,存好了之后两两比较,如果符合旗鼓相当的对手,那么就输出两个人的名字即可。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {
	public static void main(String[] args) throws  IOException {
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		int n=Integer.valueOf(br.readLine());
		p2[] p=new p2[n];
		for(int i=0;i<n;i++) {
			String[] s=br.readLine().split(" ");
			p[i]=new p2(s[0],Integer.valueOf(s[1]),Integer.valueOf(s[2]),Integer.valueOf(s[3]));		
		}
		for(int i=0;i<n;i++) {
			for(int j=i+1;j<n;j++) {
				if(Math.abs(p[i].a-p[j].a)<=5&&Math.abs(p[i].b-p[j].b)<=5&&Math.abs(p[i].c-p[j].c)<=5&&Math.abs(p[i].a+p[i].b+p[i].c-p[j].a-p[j].b-p[j].c)<=10){
					System.out.println(p[i].name+" "+p[j].name);
				}
			}
		}
	}
}
class p2{
	String name;
	int a,b,c;
	p2(String name,int aa,int bb,int cc){
		this.name=name;a=aa;b=bb;c=cc;
	}
}

(9)P5742 【深基7.例11】评等级
这题应该不用我来写解析了,题目就是教一步步怎么做的。按着题目的写练练手就好。但其实这道题完全不用结构体,而且那个学号数据没什么用,直接边读入数据边判断就行了。

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		for(int i=0;i<n;i++) {
			int a=sc.nextInt(),b=sc.nextInt(),c=sc.nextInt();
			double sum=b*0.7+c*0.3;
			if(sum>=80&&b+c>140) {
				System.out.println("Excellent");
			}
			else {
				System.out.println("Not excellent");
			}
		}
	}
}

(10)P1075 质因数分解
这道题我在循环结构那个题单里写过了,代码很简单,考察一些数论的知识。一个数只能分解成一组质数的乘积,而这题他说了会分解成两个,那么就是说只有这两个质数能被这个数整除。所以不用怕碰到合数。

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		for(int i=2;i<=n;i++) {
			if(n%i==0) {
				System.out.println(n/i);
				return;
			}
		}
	}
}

(11)P1304 哥德巴赫猜想
又是一道练习筛法的题目。先筛一遍,然后从4-N把每个偶数对应的两个质数打出来,取第一个质数最小的那种输出。

import java.util.Scanner;

public class Main {
	static boolean[] vis=new boolean[10010];
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		prime();
		for(int i=4;i<=n;i+=2) {
			pr(i);
		}
	}
	public static void pr(int n) {
		for(int i=2;i<=n;i++) {
			if(!vis[i]&&!vis[n-i]) {
				System.out.println(n+"="+i+"+"+(n-i));
				return;
			}
		}
	}
	public static void prime() {
		vis[0]=vis[1]=true;
		for(int i=2;i<=10000;i++) {
			if(i*i>10000) {
				break;
			}
			if(!vis[i]) {
				for(int j=i*2;j<=10000;j+=i) {
					vis[j]=true;
				}
			}
		}
	}
}

(12)P1217 [USACO1.5]回文质数 Prime Palindromes
循环结构题单里做过的一题,要根据一些数学知识删掉四位数,六位数和八位数,然后在剩下的位数里面根据一些质数和回文数的特征来进行有条件的筛选。

import java.util.Scanner;

public class Main {
	static int[] a=new int[100000];
	public static boolean prime(int n) {
		for(int i=2;i*i<=n;i++) {
			if(n%i==0) {
				return false;
			}
		}
		return true;
	}
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int x=sc.nextInt(),y=sc.nextInt();
		int p=0;
		for(int i=2;i<10;i++) {  //一位数
			if(prime(i)) {
				a[p++]=i;
			}
		}
		a[p++]=11;   //两位数
		for(int i=1;i<10;i+=2) {  //三位数
			for(int j=0;j<10;j++) {
				if(prime(i*101+j*10)) {
					a[p++]=i*101+j*10;
				}
			}
		}
		for(int i=1;i<10;i+=2) {  //五位数
			for(int j=0;j<10;j++) {
				for(int k=0;k<10;k++) {
					if(prime(i*10001+j*1010+k*100)) {
						a[p++]=i*10001+j*1010+k*100;
					}
				}
			}
		}
		for(int i=1;i<10;i+=2) {  //五位数
			for(int j=0;j<10;j++) {
				for(int k=0;k<10;k++) {
					for(int l=0;l<10;l++) {
						if(prime(i*1000001+j*100010+k*10100+l*1000)) {
							a[p++]=i*1000001+j*100010+k*10100+l*1000;
						}
					}
				}
			}
		}
		for(int i=0;i<p;i++) {
			if(x<=a[i]&&a[i]<=y) {
				System.out.println(a[i]);
			}
		}
	}
}

(13)P2415 集合求和
一开始想暴力枚举所有的子集,后面发现数据太大了。既然它作为一门入门的题目肯定是有规律的,找规律发现,集合中每个数出现的次数都是相同的,并且每个元素会出现 2 n − 1 2^{n-1} 2n1。所以每个数加起来再乘 2 n − 1 2^{n-1} 2n1。为了防止数据溢出就用long类型存储。

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		long sum=0;
		int n=0;
		while(sc.hasNextInt()) {
			sum+=sc.nextInt();
			n++;
		}
		int res=1;
		for(int i=1;i<n;i++) {
			res*=2;
		}
		
		System.out.println(sum*res);
	}
}

(14)P5743 【深基7.习8】猴子吃桃
这道题有两种思考的方法,一种是正着想,我们是要求第一天的桃子数,那么我们可以循环枚举第一天的桃子数,然后模拟吃桃子的情况,直到找到第一题桃子数符合模拟情况。那么就退出

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
	    double res;
	    for (int i = 1; i <= 10000000; i++) {
	        res = i;
	        for (int j = 1; j < n; j++) {
	            res -= res / 2.0 + 1;
	        }
	        if (res == 1) {
	            System.out.println(i);
	            return;
	        }
	    }
	}
}

但假如我们倒着想,我们反正知道最后一天剩一个桃子,我们可以得出倒数第二天的桃子数,然后推出倒数第N天的,只到第一天的。这样的思路不用暴力枚举,所以在碰到大数据的时候会快很多。

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		int ans=1;
		for(int i=2;i<=n;i++) {
			ans=(ans+1)*2;
		}
		System.out.println(ans);
	}
}

(15)P5744 【深基7.习9】培训
这题也可以边读入边输出,完全不用结构体。无非就是年龄加1,然后成绩乘1.2,如果大于满分就等于满分。

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		sc.nextLine();
		for(int i=0;i<n;i++) {
			String[] s=sc.nextLine().split(" ");
			System.out.println(s[0]+" "+(Integer.valueOf(s[1])+1)+" "+((int)Math.min(600, Integer.valueOf(s[2])*1.2)));
		}
	}
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值