(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种情况,第一种原字母直接输出,但二种是前后字母相等去掉-号,第三种是根据字母的前后关系和参数来制作一个字符串替代-号
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
10n,那么位数就等于n+1,那么我们怎么让
2
P
−
1
2^P-1
2P−1变成那种格式呢,首先我们知道
2
P
−
1
2^P-1
2P−1在位数上等于
2
P
2^P
2P,因为P>1000,减1不会退位。可是
2
P
2^P
2P怎么转换呢?2可以通过
1
0
log
10
2
10^{\log_{10}2}
10log102来表示,那么我们把
2
P
2^P
2P底数2换成
1
0
log
10
2
10^{\log_{10}2}
10log102,那么得出
(
1
0
log
10
2
)
P
(10^{\log_{10}2})^P
(10log102)P。所以位数(
log
10
2
)
∗
p
+
1
\log_{10}2)*p+1
log102)∗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"));
}
}