洛谷题单:【算法1-1】模拟与高精度

(1)P1042 乒乓球
这是一道模拟题,有11分制和21分制,然后每种规则的结束这一场的条件是到达11分或者21分,并且双方球员的比分差距大于等于2,那么就开始下一场比赛。直到字符串到达E。我们一开始建立4个数组分别储存球员A和球员B在两种规则下的比分,然后遍历字符串模拟比赛就行啦。

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));
		StringBuilder sb=new StringBuilder();
		int[] a1=new int[10000],a2=new int[10000],b1=new int[10000],b2=new int[10000];
		while(true) {
			String s=br.readLine();
			if(s.indexOf('E')!=-1) {
				sb.append(s.substring(0,s.indexOf('E')));
				break;
			}
			else {
				sb.append(s);
			}
		}
		int p=0,q=0;
		for(int i=0;i<sb.length();i++) {
			if(sb.charAt(i)=='W') {
				a1[p]++;a2[q]++;
			}
			else {
				b1[p]++;b2[q]++;
			}
			if(Math.abs(a1[p]-b1[p])>=2&&Math.max(a1[p], b1[p])>=11) p++;
			if(Math.abs(a2[q]-b2[q])>=2&&Math.max(a2[q], b2[q])>=21) q++;
		}
		for(int i=0;i<=p;i++) {
			System.out.println(a1[i]+":"+b1[i]);
		}
		System.out.println();
		for(int i=0;i<=q;i++) {
			System.out.println(a2[i]+":"+b2[i]);
		}
	}
}

(2)P2670 扫雷游戏
一开始以为要用深搜,后面发现不用,因为只要判断周围的八个方向有几个雷就好了。那么遍历这张地图,如果碰到?就对周围八个方向进行寻找看看有几个雷,然后输出这个数字。如果碰到*,直接输出。

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[] dx={1,0,-1,0,-1,1,1,-1};
		int[] dy={0,1,0,-1,-1,-1,1,1};
		String[] s=br.readLine().split(" ");
		int n=Integer.valueOf(s[0]),m=Integer.valueOf(s[1]);
		char[][] arr=new char[n][m];
		char[][] res=new char[n][m];
		for(int i=0;i<n;i++) {
			arr[i]=br.readLine().toCharArray();
		}
		for(int i=0;i<n;i++) {
			for(int j=0;j<m;j++) {
				if(arr[i][j]=='*') {
					System.out.print('*');
				}
				else {
					int sum=0;
					for(int k=0;k<8;k++) {
						int tx=i+dx[k];
						int ty=j+dy[k];
						if(0<=tx&&tx<n&&0<=ty&&ty<m&&arr[tx][ty]=='*') {
							sum++;
						}
					}
					System.out.print(sum);
				}
			}
			System.out.println();
		}
	}
}

(3)P1563 玩具谜题
用两个数组分别储存人的名字和他们朝的方向,然后顺着题目意思进行模拟,根据他们的朝向来判断是正着遍历数组还是反着遍历数组。


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));
		String[] ss=br.readLine().split(" ");
		int n=Integer.valueOf(ss[0]);
		int m=Integer.valueOf(ss[1]);
		boolean[] arr1=new boolean[n];
		String[] arr2=new String[n];
		for(int i=0;i<n;i++) {
			ss=br.readLine().split(" ");
			if(ss[0].equals("1")) {
				arr1[i]=true;
			}
			arr2[i]=ss[1];
		}
		int p=0;
		for(int i=0;i<m;i++) {
			ss=br.readLine().split(" ");
			int x=Integer.valueOf(ss[0]);
			int y=Integer.valueOf(ss[1]);
			if(x==0&&arr1[p]==true||x==1&&arr1[p]==false) {
					p+=y;
			}
			else {
					p-=y;
			}
			if(p<0) {
				p+=n;
			}
			if(p>=n) {
				p-=n;
			}
		}
		System.out.println(arr2[p]);
	}
}

(4)P1601 A+B Problem(高精)
高精度的题目对java来说和不是问题,因为java有BigInteger类,做这种题目就是秒杀


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

public class Main {
	public static void main(String[] args) throws IOException {
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		String a=br.readLine();
		String b=br.readLine();
		BigInteger aa=new BigInteger(a);
		BigInteger bb=new BigInteger(b);
		aa=aa.add(bb);
		System.out.println(aa);
	}
}

(5)P1303 A*B Problem
和上一题同理,用大数类是不会溢出的


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

public class Main {
	public static void main(String[] args) throws IOException {
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		String a=br.readLine();
		String b=br.readLine();
		BigInteger aa=new BigInteger(a);
		BigInteger bb=new BigInteger(b);
		aa=aa.multiply(bb);
		System.out.println(aa);
	}
}

(6)P1009 阶乘之和
这题和是计算1-n的阶乘,然后累加起来。其实考察的还是高精度,用Java的大数类就可以得出结果。

import java.math.BigInteger;
import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		BigInteger sum=new BigInteger("0");
		for(int i=1;i<=n;i++) {
			sum=sum.add(f(i));
		}
		System.out.println(sum);
	}
	public static BigInteger f(int n) {
		if(n==1)
			return new BigInteger("1");
		return new BigInteger(n+"").multiply(new BigInteger(f(n-1)+""));
	}
}

(7)P4924 [1007]魔法少女小Scarlet
这题就是考察矩阵的旋转,只要找规律推出旋转的公式,同时开一个临时数组来保存这个旋转后的矩阵,再赋值给原来矩阵即可。
吐槽一下,java想要AC这题真的有点麻烦。因为最后两个点老是会超内存和超时,超内存的原因是一开始我每次旋转都重新开了一个二维数组,后面我直接全局开一个数组,这样就只要开一次数组,这样就不会超内存了。但在超时的问题上,一开始我把输入方法从Scanner改成BufferReader,这样倒数第二个点过了,然后再把输出方法改PrintWriter,这样最后一个点也过了。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Scanner;

public class Main{
	static int[][] arr,a;
	public static void main(String[] args) throws IOException {
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		PrintWriter out=new PrintWriter(System.out);
		String[] s=br.readLine().split(" ");
		int n=Integer.valueOf(s[0]),m=Integer.valueOf(s[1]);
		arr=new int[n+1][n+1];
		a=new int[n+1][n+1];
		int p=1,x,y,r,z;
		for(int i=1;i<=n;i++) {
			for(int j=1;j<=n;j++) {
				arr[i][j]=p++;
			}
		}
		for(int i=0;i<m;i++) {
			s=br.readLine().split(" ");
			x=Integer.valueOf(s[0]);y=Integer.valueOf(s[1]);r=Integer.valueOf(s[2]);z=Integer.valueOf(s[3]);
			change(x,y,r,z);
		}
		for(int i=1;i<=n;i++) {
			for(int j=1;j<=n;j++) {
				out.print(arr[i][j]+" ");
			}
			out.println();
		}
		out.close();
	}
	public static void change(int x,int y,int r,int z) {
		for(int i=0;i<(2*r+1);i++) {
			for(int j=0;j<(2*r+1);j++) {
				if(z==0) a[i][j]=arr[(2*r+1)-j+(x-r)-1][i+(y-r)];
				else a[i][j]=arr[j+(x-r)][(2*r+1)-i+(y-r)-1];
			}
		}
		for(int i=x-r;i<=x+r;i++) {
			for(int j=y-r;j<=y+r;j++) {
				arr[i][j]=a[i-(x-r)][j-(y-r)];
			}
		}
		
	}
}

(8)P1328 生活大爆炸版石头剪刀布
一道简单的模拟题。按照它制定的规则,也就是那张表,来判断胜负即可。然后记录两人的得分,最后把得分输出


import java.util.Scanner;

public class Main {
	static int p1=0,p2=0,score1=0,score2=0;
	static int n1,n2;
	static int[] arr1,arr2;
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		n1=sc.nextInt();
		n2=sc.nextInt();
		arr1=new int[n1];
		arr2=new int[n2];
		for(int i=0;i<n1;i++) {
			arr1[i]=sc.nextInt();
		}
		for(int i=0;i<n2;i++) {
			arr2[i]=sc.nextInt();
		}
		for(int i=0;i<n;i++) {
			judge();
		}
		System.out.println(score1+" "+score2);
	}
	public static void judge() {
		if(p1==n1) {
			p1=0;
		}
		if(p2==n2) {
			p2=0;
		}
		if(arr1[p1]==arr2[p2]) {
		}
		else if(arr1[p1]==0&&(arr2[p2]==2||arr2[p2]==3)) {
			score1++;
		}
		else if(arr1[p1]==1&&(arr2[p2]==0||arr2[p2]==3)) {
			score1++;
		}
		else if(arr1[p1]==2&&(arr2[p2]==1||arr2[p2]==4)) {
			score1++;
		}
		else if(arr1[p1]==3&&(arr2[p2]==2||arr2[p2]==4)) {
			score1++;
		}
		else if(arr1[p1]==4&&(arr2[p2]==0||arr2[p2]==1)) {
			score1++;
		}
		else {
			score2++;
		}
		p1++;
		p2++;
	}
}

(9)P1518 [USACO2.4]两只塔姆沃斯牛 The Tamworth Two
这道题是一道模拟题,设置两个人的坐标和朝向,然后设置一个方向数组来改变两人的朝向。但这题有一个难点就是如何判断牛和人是否会相遇,一种方法是直接暴力for循环,自己设置一个大一点的循环次数,如果没找到,我们就认为找不到,这种思路比较简单,但是没有足够的理论依据。第二种思路是设置一个布尔型数组来判断牛和人的状态,如果牛和人的状态完全相同的情况出现了第二次,就说明他们陷入了循环,即永远找不到。

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

public class Main {
	public static void main(String[] args) throws IOException {
		int[] dir_x= {-1,0,1,0};
		int[] dir_y= {0,1,0,-1};
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		boolean[][][][][][] vis=new boolean[10][10][10][10][4][4];
		char[][] arr=new char[10][10];
		int x1=0,x2=0,y1=0,y2=0,dir1=0,dir2=0;
		for(int i=0;i<10;i++) {
			arr[i]=br.readLine().toCharArray();
			for(int j=0;j<10;j++) {
				if(arr[i][j]=='F') {
					x1=i;y1=j;
				}
				if(arr[i][j]=='C') {
					x2=i;y2=j;
				}
			}
		}
		vis[x1][y1][x2][y2][0][0]=true;
		int t=0;
		while(true) {
			t++;
			int tx=x1+dir_x[dir1],ty=y1+dir_y[dir1];
			if(0<=tx&&tx<10&&0<=ty&&ty<10&&arr[tx][ty]!='*') {
				x1=tx;y1=ty;
			}
			else {
				dir1=(dir1+1)%4;
			}
			tx=x2+dir_x[dir2];
			ty=y2+dir_y[dir2];
			if(0<=tx&&tx<10&&0<=ty&&ty<10&&arr[tx][ty]!='*') {
				x2=tx;y2=ty;
			}
			else {
				dir2=(dir2+1)%4;
			}
			if(x1==x2&&y1==y2) {    //找到了
				System.out.println(t);
				return;
			}
			if(vis[x1][y1][x2][y2][dir1][dir2]) {   //永远找不到
				System.out.println(0);
				return;
			}
			vis[x1][y1][x2][y2][dir1][dir2]=true;  //标记这种情况已经出现过了
		}
		
	}
}

(10)P1067 多项式输出
这题就是几种情况,X=0的时候不输出,X=1和X=-1时候只输出正负号,其他情况的时候把系数输出。另外要特判下第一项和最后一项,因为最后一项没有字母X的,第一项如果是正数前面是不用写+号的。


import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		boolean sign=false;
		for(int i=n;i>=0;i--) {
			int x=sc.nextInt();
			if(sign==false&&x!=0) {                         //特判第一项
				if(x==0) {
					continue;
				}
				else if(x==1) {
					System.out.print("");
				}
				else if(x==-1) {
					System.out.print("-");
				}
				else
					System.out.print(x);
				sign=true;
			}
			else if(i==0) {              //特判最后一项
				if(x>0) {
					System.out.print("+"+x);
				}
				else if(x<0) {
					System.out.print(x);
				}
				else if(x==0) {
					continue;
				}
				break;
			}
			else if(x==0) {
				continue;
			}
			else if(x>1) {
				System.out.print("+"+x);
			}
			else if(x==1) {
				System.out.print("+");
			}
			else if(x==-1) {
				System.out.print("-");
			}
			else {
				System.out.print(x);
			}
			if(i!=1) {
			System.out.print("x^"+i);
			}
			else {
				System.out.print("x");
			}
			
		}
	}
}

(11)P1098 字符串的展开
这道题是一道挺复杂一些的模拟题,情况的种类比较多,我也是弄了挺久才AC的,题目本身并不难。但是细节太多了,比如连续的-,比如如果前后相同要去掉-,比如前后一个是字母一个是数字的。。。
思路:分为3种情况,第一种原字母直接输出,但二种是前后字母相等去掉-号,第三种是根据字母的前后关系和参数来制作一个字符串替代-号

扫描二维码关注公众号,回复: 10161672 查看本文章
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));
		String[] s=br.readLine().split(" ");
		int p1=Integer.valueOf(s[0]),p2=Integer.valueOf(s[1]),p3=Integer.valueOf(s[2]);
		String ss=br.readLine();
		for(int i=0;i<ss.length();i++) {
			if(ss.charAt(i)=='-'&&(i-1)>=0&&(i+1)<ss.length()&&judge(ss.charAt(i-1),ss.charAt(i+1))) {
				if(ss.charAt(i+1)-ss.charAt(i-1)!=1) {
					StringBuilder sb=new StringBuilder();
					for(int j=ss.charAt(i-1)+1;j<ss.charAt(i+1);j++) {
						for(int k=0;k<p2;k++) {
							if(p1==3) sb.append('*');
							else if(p1==1||ss.charAt(i-1)<='9')sb.append((char)(j));
							else if(p1==2)sb.append((char)(j-32));
						}
					}
					if(p3==2) System.out.print(sb.reverse());
					else System.out.print(sb);	
				}
			}
			else  System.out.print(ss.charAt(i));
		}
	}
	public static boolean judge(char x,char y) {
		if('0'<=x&&x<='9'&&'0'<=y&&y<='9') if(x<y)return true;
		if('a'<=x&&x<='z'&&'a'<=y&&y<='z')if(x<y)return true;
		return false;
	}
}

(12)P1065 作业调度方案
很难的一道模拟题,暂时很好的解决思路

(13)P1786 帮贡排序
作为一道提高难度的题它算是比较简单的,主要要弄清楚题目意思。首先把数据读入,前三个也就是帮主和副帮主是要单独用一个数组存的,因为,他们什么样进来就什么样输出。其他的人,首先按照帮贡进行排序,如果帮贡相同按照先后顺序排,然后给他们分职位。第二遍排序,按照职位排序,入宫职位相同,按照等级排序,等级相同,再按照先后顺序排序

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

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());
		peo[] p1=new peo[3];
		String[] help= {"BangZhu","FuBangZhu","HuFa","ZhangLao","TangZhu","JingYing","BangZhong"};
		String[] s=br.readLine().split(" ");
		p1[0]=new peo(0,s[0],0,Integer.valueOf(s[2]),Integer.valueOf(s[3]));
		for(int i=1;i<3;i++) {
			s=br.readLine().split(" ");
			p1[i]=new peo(i,s[0],1,Integer.valueOf(s[2]),Integer.valueOf(s[3]));
		}
		peo[] p2=new peo[n-3];
		for(int i=0;i<n-3;i++) {
			s=br.readLine().split(" ");
			p2[i]=new peo(i,s[0],0,Integer.valueOf(s[2]),Integer.valueOf(s[3]));
		}
		MyCMP1 cmp1=new MyCMP1();
		MyCMP2 cmp2=new MyCMP2();
		Arrays.sort(p2,cmp1);
		for(int i=0;i<n-3;i++) {
			if(i<2)p2[i].job=2;
			else if(i<6) p2[i].job=3;
			else if(i<13) p2[i].job=4;
			else if(i<38) p2[i].job=5;
			else p2[i].job=6;
		}
		for(int i=0;i<3;i++) {
			System.out.println(p1[i].name+" "+help[p1[i].job]+" "+p1[i].rank);
		}
		Arrays.sort(p2,cmp2);
		for(int i=0;i<n-3;i++) {
			System.out.println(p2[i].name+" "+help[p2[i].job]+" "+p2[i].rank);
		}
		
	}
}
class peo {
	int id,job,money,rank;
	String name;
	peo(int id,String name,int job,int money,int rank){
		this.id=id;this.name=name;this.job=job;this.money=money;this.rank=rank;
	}
}
class MyCMP1 implements Comparator<peo>{
	@Override
	public int compare(peo o1, peo o2) {
		if(o2.money==o1.money)return o1.id-o2.id;
		return o2.money-o1.money;
	}
}
class MyCMP2 implements Comparator<peo>{//职位相同,按照经验先后排序
	@Override
	public int compare(peo o1, peo o2) {
		if(o2.job==o1.job&&o2.rank==o1.rank) return o1.id-o2.id;
		if(o2.job==o1.job)return o2.rank-o1.rank;
		return o1.job-o2.job;
	}
}


(14)P1591 阶乘数码
经历了两道连续的提高难度的题,再看一眼普及的题目就感觉简单不少。这么大的阶乘数肯定要用高精度,然后逐位判断是不是题目要求的数码即可。

import java.math.BigInteger;
import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int t=sc.nextInt();
		while(t-->0) {
			BigInteger n=sc.nextBigInteger();
			n=f(n);
			int sum=0;
			char m=(char)(sc.nextInt()+'0');
			String s=n.toString();
			for(int i=0;i<s.length();i++) {
				if(s.charAt(i)==m)sum++;
			}
			System.out.println(sum);
		}
	}
	public static BigInteger f(BigInteger n) {
		if(n.compareTo(new BigInteger("1"))==0) {
			return new BigInteger("1");
		}
		return n.multiply(f(n.subtract(new BigInteger("1"))));
	}
}

(15)P1249 最大乘积
这道题是考察数论+高精度,高精度对java来说不算什么,难点就在数论上面。乘积既然是拆的越多项相乘越多,这个一般都能想到。但是当拆的项数一样的情况下,怎么样能使得乘积最大呢?这就要一点思考了,当然是所有数字的整体越大越好。就是说比如2+3+7和3+4+5,两者和相同,也都是3项,但是后面的数字的乘积要大于前面的。所以我们取2 3 4…直到最后一项不够的时候,我们把最后一项差的数字用前面一项补齐。就拿样例10来说
,我们取2,那么剩8,再取3,剩5,再取4,剩1,再取5,不够还差4,那么我们用前面的4来填满5.这样235=30.

import java.math.BigInteger;
import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt(),p=2;
		while(true) {
			n-=p;
			if(n<=0) {
				break;
			}
			p++;
		}
		BigInteger sum=new BigInteger("1");
		for(int i=2;i<=p;i++) {
			if(n==-i) {
				continue;
			}
			System.out.print(i+" ");
			sum=sum.multiply(new BigInteger(i+""));
		}
		System.out.println();
		System.out.println(sum);
	}
}

(16)P1045 麦森数
又是一道数学题。第一个求位数的问题要推导数学公式,我们知道如果一个数能表示成 1 0 n 10^n ,那么位数就等于n+1,那么我们怎么让 2 P 1 2^P-1 变成那种格式呢,首先我们知道 2 P 1 2^P-1 在位数上等于 2 P 2^P ,因为P>1000,减1不会退位。可是 2 P 2^P 怎么转换呢?2可以通过 1 0 log 10 2 10^{\log_{10}2} 来表示,那么我们把 2 P 2^P 底数2换成 1 0 log 10 2 10^{\log_{10}2} ,那么得出 ( 1 0 log 10 2 ) P (10^{\log_{10}2})^P 。所以位数( log 10 2 ) p + 1 \log_{10}2)*p+1
第二问就是标准的高精度快速幂了。如果直接用大数类的话是会超时的,但我这里还是这样写了。

import java.math.BigInteger;
import java.util.Scanner;

public class Main{
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int p=sc.nextInt();
		int x=(int)(Math.log10(2)*p+1);
		System.out.println(x);
		String s=fast_pow(new BigInteger("2"),p).toString();
		StringBuilder  sb=new StringBuilder();
		if(s.length()<500) {
			for(int i=1;i+s.length()<=500;i++) {
				sb.append('0');
			}
			sb.append(s);
		}
		else {
			sb.append(s.substring(s.length()-500,s.length()));
		}
		for(int i=0;i<500;i+=50)
			System.out.println(sb.substring(i,i+50));
	}
	public static BigInteger fast_pow(BigInteger base,int power) {
		BigInteger res=new BigInteger("1");
		while(power>0) {
			if(power%2==1) {
				res=res.multiply(base);
			}
			power>>=1;
			base=base.multiply(base);
		}
		return res.subtract(new BigInteger("1"));
	}
}

发布了26 篇原创文章 · 获赞 18 · 访问量 4630

猜你喜欢

转载自blog.csdn.net/qq_43751506/article/details/104960373