(1)P1428 小鱼比可爱
第一题果然一如既往的水题,两个循环。外层循环表示那只鱼正在往左看,内层循环表示被看的鱼。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int[] arr=new int[n];
for(int i=0;i<n;i++) {
arr[i]=sc.nextInt();
int count=0;
for(int j=i-1;j>=0;j--) {
if(arr[i]>arr[j]) {
count++;
}
}
System.out.print(count+" ");
}
}
}
(2)P1427 小鱼的数字游戏
这题着实比第一题还水,用数组存每个元素,倒着输出来即可。但我这里皮一下用栈进行储存,因为栈有先进先出的原则,这样就不用倒序输出了。
import java.util.Scanner;
import java.util.Stack;
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
Stack<Integer> s=new Stack<Integer>();
while(true) {
int x=sc.nextInt();
if(x==0) {
break;
}
s.push(x);
}
while(!s.isEmpty()) {
System.out.print(s.pop()+" ");
}
}
}
(3)P5727 【深基5.例3】冰雹猜想
和第二题一样的思路呀,把n的变化存到数组里,然后倒序输出。但这里用栈会比较好,因为不知道数组应该开多大。
import java.util.Scanner;
import java.util.Stack;
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
Stack<Integer> s=new Stack<Integer>();
while(n!=1) {
s.push(n);
if(n%2==0) {
n/=2;
}
else {
n=n*3+1;
}
}
System.out.print(1+" ");
while(!s.isEmpty()) {
System.out.print(s.pop()+" ");
}
}
}
(4)P1047 校门外的树
这道题如果数据搞难点就有一些其他的优化解法,线段树什么的。但这题在入门里肯定就是用数组扫就完事了,毕竟数据才10000。第一遍扫描,把所有要去掉的树抹去标记,就是把false改为true,第二遍,统计还剩多少课树,就是false有多少。
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();
boolean[] arr=new boolean[n+1];
for(int i=0;i<m;i++) {
int x=sc.nextInt(),y=sc.nextInt();
for(int j=x;j<=y;j++) {
arr[j]=true;
}
}
int sum=0;
for(int i=0;i<=n;i++) {
if(!arr[i]) {
sum++;
}
}
System.out.println(sum);
}
}
(5)P5728 【深基5.例5】旗鼓相当的对手
用4个一维数组分别储存各个科目的分数和总分,然后用两层循环进行逐个判断是否满足各个科目绝对值差小于5,总分绝对值差小于10.并且计数。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int[] a=new int[n],b=new int[n],c=new int[n],d=new int[n];
for(int i=0;i<n;i++) {
a[i]=sc.nextInt();
b[i]=sc.nextInt();
c[i]=sc.nextInt();
d[i]=a[i]+b[i]+c[i];
}
int count=0;
for(int i=0;i<n;i++) {
for(int j=i+1;j<n;j++) {
if(Math.abs(a[i]-a[j])<=5&&Math.abs(b[i]-b[j])<=5&&Math.abs(c[i]-c[j])<=5&&Math.abs(d[i]-d[j])<=10) {
count++;
}
}
}
System.out.println(count);
}
}
(6)P5729 【深基5.例7】工艺品制作
这个题目乍一看有点唬人,看到那么多个参数。其实这道题本质和第四题校门外的树是一样的,只是这道题从一维变成了一个三维的。所有我们建立一个三维数组,来存储这个大的立方体,再用三层循环去消除掉中间的立方体,最后遍历下这个立方体剩的小立方体个数即可。数据量很小,不用怕3重循环会超时。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int w=sc.nextInt(),s=sc.nextInt(),h=sc.nextInt();
int q=sc.nextInt();
boolean[][][] arr=new boolean[w+1][s+1][h+1];
for(int i=0;i<q;i++) {
int x1=sc.nextInt(),y1=sc.nextInt(),z1=sc.nextInt(),x2=sc.nextInt(),y2=sc.nextInt(),z2=sc.nextInt();
for(int a=x1;a<=x2;a++) {
for(int b=y1;b<=y2;b++) {
for(int c=z1;c<=z2;c++) {
arr[a][b][c]=true;
}
}
}
}
int sum=0;
for(int i=1;i<=w;i++) {
for(int j=1;j<=s;j++) {
for(int k=1;k<=h;k++) {
if(!arr[i][j][k]) {
sum++;
}
}
}
}
System.out.println(sum);
}
}
(7)P2550 [AHOI2001]彩票摇奖
建立两个数组,一个数组存放特等奖到没有奖的个数,另一个数组是一个布尔类型的数组,将下标是有奖号码的值置为true。然后去遍历买的彩票的号码,如果号码在对应的数组值是true就说明中奖了,是false则没有,每一次循环后用第一个数组记录是几等奖。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
boolean[] arr=new boolean[34];
int[] res=new int[8];
for(int i=0;i<7;i++) {
arr[sc.nextInt()]=true;
}
for(int i=0;i<n;i++) {
int sum=0;
for(int j=0;j<7;j++) {
if(arr[sc.nextInt()]) {
sum++;
}
}
res[sum]++;
}
for(int i=7;i>0;i--) {
System.out.print(res[i]+" ");
}
}
}
(8)P2615 神奇的幻方
一道神奇的模拟题,这题不用什么技巧,建立个二维数组,然后照着它的规则,一步步的改变坐标然后赋值,知道把整个二维数组填满,输出这个幻方即可。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int[][] arr=new int[n][n];
int x=0,y=n/2;
arr[x][y]=1;
for(int i=2;i<=n*n;i++) {
if(x==0&&y!=n-1) {
x=n-1;
y++;
}
else if(y==n-1&&x!=0) {
x--;
y=0;
}
else if(x==0&&y==n-1) {
x++;
}
else {
if(arr[x-1][y+1]==0) {
x--;
y++;
}
else {
x++;
}
}
arr[x][y]=i;
}
for(int i=0;i<n;i++) {
for(int j=0;j<n;j++) {
System.out.print(arr[i][j]+" ");
}
System.out.println();
}
}
}
(9)P5730 【深基5.例10】显示屏
一道 普及/提高-的题目,这个的意思就是让你画数字图形。千万不要一个个画,那肯定不可能,因为你画完第一个数,都已经换行换到最后一行了,再要从新回到第一行是很难实现的,所以这题应该所有数字一起画。一行一行的画。一共画五行。也就是要5个单独的循环。这道提高题算是比较水的了,可能因为代码比较大放在提高难度的吧,但我觉得大部分都是重复的代码。
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();
String s=sc.nextLine();
for(int i=0;i<n;i++) { //第一行
if(s.charAt(i)=='0'||s.charAt(i)=='2'||s.charAt(i)=='3'||s.charAt(i)=='5'||s.charAt(i)=='6'||s.charAt(i)=='7'||s.charAt(i)=='8'||s.charAt(i)=='9') {
System.out.print("XXX");
}
else if(s.charAt(i)=='1') {
System.out.print("..X");
}
else {
System.out.print("X.X");
}
if(i!=n-1)
System.out.print(".");
}
System.out.println();
for(int i=0;i<n;i++) { //第二行
if(s.charAt(i)=='0'||s.charAt(i)=='4'||s.charAt(i)=='8'||s.charAt(i)=='9') {
System.out.print("X.X");
}
else if(s.charAt(i)=='1'||s.charAt(i)=='2'||s.charAt(i)=='3'||s.charAt(i)=='7') {
System.out.print("..X");
}
else {
System.out.print("X..");
}
if(i!=n-1)
System.out.print(".");
}
System.out.println();
for(int i=0;i<n;i++) { //第三行
if(s.charAt(i)=='0') {
System.out.print("X.X");
}
else if(s.charAt(i)=='1'||s.charAt(i)=='7') {
System.out.print("..X");
}
else {
System.out.print("XXX");
}
if(i!=n-1)
System.out.print(".");
}
System.out.println();
for(int i=0;i<n;i++) { //第四行
if(s.charAt(i)=='0'||s.charAt(i)=='6'||s.charAt(i)=='8') {
System.out.print("X.X");
}
else if(s.charAt(i)=='2') {
System.out.print("X..");
}
else {
System.out.print("..X");
}
if(i!=n-1)
System.out.print(".");
}
System.out.println();
for(int i=0;i<n;i++) { //第五行
if(s.charAt(i)=='0'||s.charAt(i)=='2'||s.charAt(i)=='3'||s.charAt(i)=='5'||s.charAt(i)=='6'||s.charAt(i)=='8'||s.charAt(i)=='9') {
System.out.print("XXX");
}
else {
System.out.print("..X");
}
if(i!=n-1)
System.out.print(".");
}
}
}
(10)P1554 梦中的统计
这题题目说的不清不楚的,但看了样例就知道,它是问M和N两个数之间,0-9这10个数字分别共出现了多少次。比如131这个数,1出现了两次,3出现了一次。数据量还行,暴力枚举就行。用个数组存到结果
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[] arr=new int[10];
for(int i=a;i<=b;i++) {
int ii=i;
while(ii!=0) {
arr[ii%10]++;
ii/=10;
}
}
for(int i=0;i<10;i++) {
System.out.print(arr[i]+" ");
}
}
}
(11)P2141 珠心算测验
这道题用暴力三重循环对每个数进行遍历是肯定可以的,注意不能选重复的数字。但我这里用了一种比较快的方法,用两个循环就可以搞定,首先把数据读进来用数组的下标存着,true代表这个数存在。然后两层循环去找两数的和,对于每个两个数的和,首先判断这个两个数的和存在不存在,如果存在,再用另一个布尔型数组存起来。最后输出存在的两数之和。
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());
int[] arr=new int[n];
boolean[] vis=new boolean[20005];
boolean[] vis2=new boolean[20005];
String[] s=br.readLine().split(" ");
for(int i=0;i<n;i++) {
arr[i]=Integer.valueOf(s[i]);
vis[arr[i]]=true;
}
int count=0;
for(int i=0;i<n;i++) {
for(int j=i+1;j<n;j++) {
if(vis[arr[i]+arr[j]]) {
vis2[arr[i]+arr[j]]=true;
}
}
}
for(int i=0;i<vis2.length;i++) {
if(vis2[i]) {
count++;
}
}
System.out.println(count);
}
}
(12)P1614 爱与愁的心痛
这道题如果选取的m长度不固定,值可以为负数。那么这道题的灵活性会高一些,但固定了长度,那么线性扫一遍,维护一个最小值就可以。
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();
int min=Integer.MAX_VALUE;
int[] arr=new int[n];
for(int i=0;i<n;i++) {
arr[i]=sc.nextInt();
}
for(int i=0;i<n-m+1;i++) {
int sum=0;
for(int j=i;j<m+i;j++) {
sum+=arr[j];
}
min=Math.min(min, sum);
}
System.out.println(min);
}
}
(13)P2911 [USACO08OCT]Bovine Bones G
数据规模不超过100的题,直接来个数组记录每个数出现的频率,三重循环模拟三个筛子,最后输出频率最大的那个。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int s1=sc.nextInt();
int s2=sc.nextInt();
int s3=sc.nextInt();
int[] arr=new int[100];
for(int i=1;i<=s1;i++) {
for(int j=1;j<=s2;j++) {
for(int k=1;k<=s3;k++) {
arr[i+j+k]++;
}
}
}
int max=0,index=-1;
for(int i=1;i<=s1+s2+s3;i++) {
if(arr[i]>max) {
max=arr[i];
index=i;
}
}
System.out.println(index);
}
}
(14)P1161 开灯
这题看起来给的数据量很大,但其实作为一道入门题,它没有卡数据,模拟是可以做出来的。根据题目,编号不会超过2000000,那么创建一个2000010的布尔数组来判断开关。两个for循环模拟改变开关,最后找剩下那个开着的灯。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
boolean[] arr=new boolean[2000010];
for(int i=0;i<n;i++) {
double a=sc.nextDouble();
int t=sc.nextInt();
for(int j=1;j<=t;j++) {
arr[(int)(a*j)]=!arr[(int)(a*j)];
}
}
for(int i=1;i<arr.length;i++) {
if(arr[i]==true) {
System.out.println(i);
return;
}
}
}
}
这道巧妙做法是用位运算,因为异或运算有个功能是会消除成对出现的数,因为只剩一盏灯,所以只会留下那个剩的灯。代码简介,而且速度更快。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt(),ans=0;
for(int i=0;i<n;i++) {
double a=sc.nextDouble();
int t=sc.nextInt();
for(int j=1;j<=t;j++) {
ans^=(int)(a*j);
}
}
System.out.println(ans);
}
}
(15)P5731 【深基5.习6】蛇形方阵
我觉得这道题作为一个入门的题思路并不困难,有些大佬说要考虑要转多少层,其实这题完全不用考虑,因为我们是从1一直加到nn的,也就是说,只要我们定义一个循环,让i从1加到nn,只要我们不覆盖前面的值,到循环结束了自然就退出了。
思路:这题题意很简单,就是让我们绕着这个nn的正方形转圈,但是什么时候转向呢?肯定是要到边界的时候转向,首先我们考虑最外层,我们站在起始位置(0,0)我们先往右走,走到了最后一列,我们就要转向向下走,这里很好控制,无非是建立一个判断条件y=n-1,我们转向,然后在最后一行,同样,我们转向,同理。
但是,我们第三次转向后,我们在倒退的时候,即x–的时候,我们不能再退了,再退就把1覆盖了。所以,这里我们就要加个if判断,如果退到了x=1的时候,并且我们已经转向了3次(这里要加转向3次是因为在右边x++的时候,也会经历x=1),那么我们就重置转向为0,从新开始向右走。
一个新的问题来了,我们在第二次判断边界的时候和第一次可不一样,第一次是y=n-1,第二次明显是y==n-1再-1,所以我们一定要加个变量m控制,初始值置为0,重置转向后m++,控制条件改为y=n-m,后面其他的转向条件也改成这样的形式,这样就形成了一个通式。可以不覆盖的循环转圈,直到外层的值i到nn,代码虽然比较长,但其实都是一些简单的判断。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int[][] arr=new int[n][n];
int sign=0;
int x=0,y=0;
arr[0][0]=1;
int m=0;
for(int i=2;i<=n*n;i++) {
if(x==m&&y==n-m-1) {
sign++;
}
else if(x==n-1-m&&y==n-m-1) {
sign++;
}
else if(x==n-1-m&&y==m) {
sign++;
}
if(sign==3&&x==m+1) {
m++;
sign=0;
}
if(sign==0) {
y++;
}
else if(sign==1) {
x++;
}
else if(sign==2) {
y--;
}
else if(sign==3) {
x--;
}
arr[x][y]=i;
}
for(int i=0;i<n;i++) {
for(int j=0;j<n;j++) {
System.out.printf("%3d",arr[i][j]);
}
System.out.println();
}
}
}
(16)P5732 【深基5.习7】杨辉三角
这个题目应该是刚开始学语言的一道练习习题吧,杨辉三角就是等于有个公式,a[i][j]=a[i-1][j-1]+a[i-1][j]。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int[][] arr=new int[n][n];
for(int i=0;i<n;i++) {
arr[i][0]=1;
arr[i][i]=1;
}
for(int i=2;i<n;i++) {
for(int j=1;j<n-1;j++) {
arr[i][j]=arr[i-1][j]+arr[i-1][j-1];
}
}
for(int i=0;i<n;i++) {
for(int j=0;j<=i;j++) {
System.out.print(arr[i][j]+" ");
}
System.out.println();
}
}
}
(17)P1789 【Mc生存】插火把
思路很简单,就是把照亮的位置标记一下就好啦,最后统计没被标记的位置,但是这里照亮的地方比较多,所以可以用一个数组来存标记的位置,到时候标记可以直接遍历这个数组就好啦。
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
int[] dx1={2,0,-2,0,1,1,1,0,0,0,-1,-1,-1};
int[] dy1={0,2,0,-2,0,1,-1,1,0,-1,0,1,-1};
int[] dx2={-2,-2,-2,-2,-2,-1,-1,-1,-1,-1,0,0,0,0,0,1,1,1,1,1,2,2,2,2,2};
int[] dy2={-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2};
Scanner sc=new Scanner(System.in);
int n=sc.nextInt(),m=sc.nextInt(),k=sc.nextInt();
boolean[][] arr=new boolean[n][n];
for(int i=0;i<m;i++) {
int x=sc.nextInt()-1,y=sc.nextInt()-1;
for(int j=0;j<13;j++) {
if(0<=x+dx1[j]&&x+dx1[j]<n&&0<=y+dy1[j]&&y+dy1[j]<n)
arr[x+dx1[j]][y+dy1[j]]=true;
}
}
for(int i=0;i<k;i++) {
int x=sc.nextInt()-1,y=sc.nextInt()-1;
for(int j=0;j<25;j++) {
if(0<=x+dx2[j]&&x+dx2[j]<n&&0<=y+dy2[j]&&y+dy2[j]<n)
arr[x+dx2[j]][y+dy2[j]]=true;
}
}
int sum=0;
for(int i=0;i<n;i++) {
for(int j=0;j<n;j++) {
if(!arr[i][j]) {
sum++;
}
}
}
System.out.println(sum);
}
}
(18)P1319 压缩技术
又是一道模拟题,定义一个开关来控制当前是连续的0还是1,然后根据当前是0还是1向数组进行填入,当连续数字结束后,转变开关方向,进行另一个数字的填入,直到整个二维数组被填完。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int[][] arr=new int[n][n];
int x=0,y=0;
int m=sc.nextInt();
boolean flag=false;
while(x!=n) {
if(m==0) {
m=sc.nextInt();
flag=!flag;
}
m--;
if(flag)
arr[x][y]=1;
y++;
if(y==n) {
y=0;
x++;
}
}
for(int i=0;i<n;i++) {
for(int j=0;j<n;j++) {
System.out.print(arr[i][j]);
}
System.out.println();
}
}
}
(19)P1320 压缩技术(续集版)
这个题目有意思,就是把上道题目颠倒了下,刚刚是解码,现在是编码。我觉得这道题比上到题要复杂一丢丢,但主要还是控制好字符0和1的转换,遍历这个二维数组,当发现这个字符和上个不同了,说明连续数字停止了,控制开关,然后输出连续的长度
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
String s=sc.nextLine();
char[][] arr=new char[s.length()][s.length()];
arr[0]=s.toCharArray();
for(int i=1;i<s.length();i++) {
arr[i]=sc.nextLine().toCharArray();
}
System.out.print(s.length()+" ");
int sum=0;
char x='0';
boolean flag=false;
for(int i=0;i<s.length();i++) {
for(int j=0;j<s.length();j++) {
if(arr[i][j]==x) {
sum++;
}
else {
System.out.print(sum+" ");
sum=1;
flag=!flag;
if(flag) {
x='1';
}
else {
x='0';
}
}
}
}
System.out.println(sum);
}
}
(20)P1205 [USACO1.2]方块转换 Transformations
这道题考的是矩阵的翻转,就是将原矩阵进行哪种操作后能得到新矩阵,这里操作有很多,但是我们仔细观察发现,其次就两个操作,旋转90度和水平翻转,其他的操作都是将这两个操作进行多次或者组合。所以我们写两个函数分别进行旋转90度和翻转,再写一个函数判断两个矩阵是否相等。
PS:这个题难度虽然不大,但代码量是真的大。。。
这里有个技巧,旋转4次可以还原,翻转两次可以还原
import java.util.Arrays;
import java.util.Scanner;
public class Main {
static char[][] C;
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
sc.nextLine();
char[][] A=new char[n][n];
char[][] B=new char[n][n];
C=new char[n][n]; //用一个数组来存放A经过变化后的状态
for(int i=0;i<n;i++) {
A[i]=sc.nextLine().toCharArray();
}
for(int i=0;i<n;i++) {
B[i]=sc.nextLine().toCharArray();
}
for(int i=1;i<=3;i++) {
change1(A);
if(judge(C,B)) {
System.out.println(i);
return;
}
}
change1(A);
change2(A);
if(judge(C,B)) {
System.out.println(4);
return;
}
for(int i=1;i<=3;i++) {
change1(A);
if(judge(C,B)) {
System.out.println(5);
return;
}
}
change1(A);
change2(A);
if(judge(A,B)) {
System.out.println(6);
return;
}
System.out.println(7);
}
public static void change1(char[][] A) {
for(int i=0;i<A.length;i++) {
for(int j=0;j<A.length;j++) {
C[i][j]=A[A.length-j-1][i];
}
}
for(int j=0;j<A.length;j++) {
A[j]=Arrays.copyOf(C[j], A.length);
}
}
public static void change2(char[][] A) {
for(int i=0;i<A.length;i++) {
for(int j=0;j<A.length;j++) {
C[i][j]=A[i][A.length-j-1];
}
}
for(int j=0;j<A.length;j++) {
A[j]=Arrays.copyOf(C[j], A.length);
}
}
public static boolean judge(char[][] A,char[][] B) {
for(int i=0;i<A.length;i++) {
for(int j=0;j<A.length;j++) {
if(A[i][j]!=B[i][j]) {
return false;
}
}
}
return true;
}
}