刷刷笔试题~~[算数类编程]

1.[编程题]抛小球

小东和三个朋友一起在楼上抛小球,他们站在楼房的不同层,假设小东站的楼层距离地面N米,球从他手里自由落下,每次落地后反跳回上次下落高度的一半,并以此类推知道全部落到地面不跳,求4个小球一共经过了多少米?(数字都为整数)

给定四个整数A,B,C,D,请返回所求结果。

测试样例:
100,90,80,70
返回:1020
解题思路:

设整数为x,得到公式:
sn = x + x * (1 + 1/2 + 1/4 + ... + (1/2)^m)
sn = x + x * (1- (1/2)^m) / (1-1/2)
(1/2)^m 无限接近于0
sn = x + x * 2;
sn = 3x;
所以答案为 3*(A+B+C+D) 


import java.util.*;

public class Balls {
    public int calcDistance(int A, int B, int C, int D) {
        return 3*(A+B+C+D);
    }
}


递归应该也行,每次只算掉下去,再上来到一半的那部分,注意,double和(int)的强制转换


import java.util.*;
 
public class Balls {
    double distance(double n){
        if(n==0)
            return 0;
        return n+n/2+distance(n/2);
    }
    public int calcDistance(int A, int B, int C, int D) {
        return (int)(distance(A)+distance(B)+distance(C)+distance(D));
    }
}

2. [编程题] 小东分苹果

果园里有一堆苹果,一共n头(n大于1小于9)熊来分,第一头为小东,它把苹果均分n份后,多出了一个,它扔掉了这一个,拿走了自己的一份苹果,接着第二头熊重复这一过程,即先均分n份,扔掉一个然后拿走一份,以此类推直到最后一头熊都是这样(最后一头熊扔掉后可以拿走0个,也算是n份均分)。问最初这堆苹果最少有多少个。

给定一个整数n,表示熊的个数,返回最初的苹果数。保证有解。

测试样例:
2
返回:3

解题思路:

无法从后往前推,那就从n+1开始遍历,肯定会有n+1个苹果,中间判断减1后能否整除n,不符合的直接break跳出这一轮,直到最后一个熊领走


import java.util.*;

public class Apples {
    public int getInitial(int n) {
        for(int i=n+1;;i++){
            int temp=i;
            int bear=n;
            while(bear>0){
                if(temp%n==1){
                    temp=temp-(temp-1)/n-1;
                    bear--;
                }else{
                    break;
                }
            }
            if(bear==0){
                return i;
            }
        }
    }
}

3. [编程题]上台阶

有一楼梯共m级,刚开始时你在第一级,若每次只能跨上一级或者二级,要走上m级,共有多少走法?注:规定从一级到一级有0种走法。

给定一个正整数int n,请返回一个数,代表上楼的方式数。保证n小于等于100。为了防止溢出,请返回结果Mod 1000000007的值。

测试样例:
3
返回:2

解题思路:

很常见的的一个题,注意这里防止溢出那部分!!!!!所有数都要mod

不能只mod结果


import java.util.*;

public class GoUpstairs {
    public int countWays(int n) {
        if(n<=3){
            return n-1;
        }
        int  temp=0;
        int  res=2;
        int  pre=1;
        for(int i=4;i<=n;i++){
            temp=res%1000000007;
            res=(res+pre)%1000000007;
            pre=temp%1000000007;
        }
        return res%1000000007; 
    }
}

4. . 孩子们的游戏(圆圈中最后剩下的数)

每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0...m-1报数....这样下去....直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!^_^)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1)

解析:

约瑟夫环,可以找规律,但感觉通过数组或链表来模拟环还是很方便的

<span style="font-family:Microsoft YaHei;font-size:14px;">public class Solution {
    public int LastRemaining_Solution(int n, int m) {
        if(n<1||m<1)//先判断这个
            return -1;
        int count=n;//现在还剩下的人数
        int step=0;//每轮走的步数!
        int i=-1;//指针,跟着绕,保证环的特征
        int[] a=new int[n];
        //因为要求出最后剩下的那个的编号,所以不能在删除倒数第二个点的时候就退出,
        //要接着去删最后一个点,就可以得到位置了
        while(count>0){
            i++;//指向数组中的数
            if(i>=n)//记住这是一个环,通过i来保持环的特征,编号为0~n-1,所以i变为n时就要清回0了
                i=0;
            if(a[i]==-1)
                continue;//删除点的时候将值变为-1.看到-1,就结束本次循环,直接下次循环
            step++;
            if(step==m){
                a[i]=-1;
                step=0;
                count--;
            }
        }
        return i;
    }
}</span>


5.二维数组打印

有一个二维数组(n*n),写程序实现从右上角到左下角沿主对角线方向打印。

给定一个二位数组arr及题目中的参数n,请返回结果数组。

测试样例:
[[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]],4
返回:[4,3,8,2,7,12,1,6,11,16,5,10,15,9,14,13]

一个正方形矩阵,找到规律遍历的时候可以只遍历右上半部分,左下半部分是对应的,用n-1去减横纵就行

主要是找到上半部分的规律

单独把p放出来,自己控制它的++

打印完每个斜排后p++

每个斜排的行是由当前列来决定的,放在列的循环里面


import java.util.*;

public class Printer {
    public int[] arrayPrint(int[][] arr, int n) {
        // write code here
        int[] a=new int[n*n];
        int p=0;
        for(int i=n-1;i>=0;i--){
            for(int j=0;j<n-i;j++){
                a[p]=arr[j][i+j];
                a[n*n-1-p]=arr[n-1-j][n-1-i-j];
                p++;
            }
        }
        return a;
    }
}


6.[编程题]棋子翻转

在4x4的棋盘上摆满了黑白棋子,黑白两色的位置和数目随机其中左上角坐标为(1,1),右下角坐标为(4,4),现在依次有一些翻转操作,要对一些给定支点坐标为中心的上下左右四个棋子的颜色进行翻转,请计算出翻转后的棋盘颜色。

给定两个数组Af,分别为初始棋盘和翻转位置。其中翻转位置共有3个。请返回翻转后的棋盘。

测试样例:
[[0,0,1,1],[1,0,1,0],[0,1,1,0],[0,0,1,0]],[[2,2],[3,3],[4,4]]
返回:[[0,1,1,1],[0,0,1,0],[0,1,1,0],[0,0,1,0]]

解析:

一开始以为边界要处理,后来发现,超出边界的部分不用管,所以分四个方向单独完成就行

import java.util.*;

public class Flip {
    public int[][] flipChess(int[][] A, int[][] f) {
        // write code here
        for(int i=0;i<f.length;i++){
            int row=f[i][0]-1;
            int col=f[i][1]-1;
            
            if(row-1>=0){
                A[row-1][col]=(A[row-1][col])==1?0:1;
            }
            if(row+1<=3){
                A[row+1][col]=(A[row+1][col])==1?0:1;
            }
            if(col-1>=0){
                A[row][col-1]=(A[row][col-1])==1?0:1;
            }
            
            
            if(col+1<=3){
                A[row][col+1]=(A[row][col+1])==1?0:1;
            }
        }
        return A;
    }
}

7. [编程题]平均年龄

已知某公司总人数为W,平均年龄为Y岁(每年3月末计算,同时每年3月初入职新人),假设每年离职率为x,x>0&&x<1,每年保持所有员工总数不变进行招聘,新员工平均年龄21岁。 
从今年3月末开始,请实现一个算法,可以计算出第N年后公司员工的平均年龄。(结果向上取整)。 
输入描述:
输入W Y x N


输出描述:
输出第N年后的平均年龄

输入例子:
5 5 0.2 3

输出例子:
15

import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner sc=new Scanner(System.in);
        while(sc.hasNext()){
            int w=sc.nextInt();
            double y=sc.nextDouble();
            double x=sc.nextDouble();
            int n=sc.nextInt();
            while(n>0){
                n--;
                y= 21 * x + (1 - x) * (y + 1);//老员工要加一岁
            }
            System.out.println((int)Math.ceil(y));//记得向上取整,还要变成int
        }
        
    }
}


8. 小易是一个数论爱好者,并且对于一个数的奇数约数十分感兴趣。一天小易遇到这样一个问题: 定义函数f(x)为x最大的奇数约数,x为正整数。 例如:f(44) = 11.
现在给出一个N,需要求出 f(1) + f(2) + f(3).......f(N)
例如: N = 7 
f(1) + f(2) + f(3) + f(4) + f(5) + f(6) + f(7) = 1 + 1 + 3 + 1 + 5 + 3 + 7 = 21

小易计算这个问题遇到了困难,需要你来设计一个算法帮助他。


解析:

奇数的最大奇约数就是它自己

偶数的最大奇约数是它自己不停除以2,得到的那个奇数

如果n=10,f(1) + f(2) + f(3) + f(4) + f(5) + f(6) + f(7)  + f(8) + f(9) + f(10)=1+3+5+7+9+ f(2) + f(4) + f(6) + f(8) + f(10)

f(2) + f(4) + f(6) + f(8) + f(10)刚好等于f(1) + f(2) + f(3) + f(4) + f(5) 

依此类推,这些数的最大奇约数和是  奇数的和+n/2后所有数的最大奇约数和

等差数列求和:(a1+an)*n/2

所以这里n=偶数时,sum+=(n/2)*(1+n-1)/2,这是1~n中奇数的和

n=奇数时,sum+=((n+1)/2)*(1+n)/2,这也是1~n中奇数的和

求完奇数的和之后记得n=n/2,继续向下求

import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner sc=new Scanner(System.in);
        while(sc.hasNext()){
            long n=sc.nextInt();
            long sum=0;
            while(n>0){
                if(n%2==1){
                    sum+=(n+1)*(n+1)/4;
                }else{
                    sum+=n*n/4;
                }
                n=n/2;
            }
            System.out.println(sum);
        }
    }
}


9.[编程题]钓鱼比赛

ss请cc来家里钓鱼,鱼塘可划分为n*m的格子,每个格子有不同的概率钓上鱼,cc一直在坐标(x,y)的格子钓鱼,而ss每分钟随机钓一个格子。问t分钟后他们谁至少钓到一条鱼的概率大?为多少?

输入描述:
第一行五个整数n,m,x,y,t(1≤n,m,t≤1000,1≤x≤n,1≤y≤m);
接下来为一个n*m的矩阵,每行m个一位小数,共n行,第i行第j个数代表坐标为(i,j)的格子钓到鱼的概率为p(0≤p≤1)
输出描述:
输出两行。第一行为概率大的人的名字(cc/ss/equal),第二行为这个概率(保留2位小数)
输入例子:
2 2 1 1 1
0.2 0.1
0.1 0.4
输出例子:
equal
0.20

解析:

因为是随机选取,所以ss选到所有的池子概率是相等的,所以ss可以调到鱼的概率等于所有池子加起来/池子的数量

t分钟至少钓一条鱼,用对立事件  1-(1-s)^t

这道题要注意的一个地方是,从控制台读数据,如果一个一个读可能会超时,要一行一行读


import java.util.*;
public class Main {
	public static void main(String[] args){
		Scanner sc=new Scanner(System.in);
		while(sc.hasNext()){
			int n=sc.nextInt();
			int m=sc.nextInt();
			int x=sc.nextInt();
			int y=sc.nextInt();
			int t=sc.nextInt();
			sc.nextLine();//这个地方是在换行
			double[][] map=new double[n][m];
			double sum=0;
			for(int i=0;i<n;i++){
				String[] s=sc.nextLine().split(" ");
				for(int j=0;j<m;j++){
					map[i][j]=Double.parseDouble(s[j]);
					sum+=map[i][j];
				}
			}
			double c=map[x-1][y-1];
			double s=sum/(n*m);
			fish(t,c,s);
		}
	}
	public static void fish(int t,double c,double s){
		if(c>s){
			System.out.println("cc");
			System.out.println(String.format("%.2f", 1-Math.pow(1-c, t)));
		}else if(s>c){
			System.out.println("ss");
			System.out.println(String.format("%.2f", 1-Math.pow(1-s, t)));
		}else {
			System.out.println("equal");
			System.out.println(String.format("%.2f", 1-Math.pow(1-c, t)));
		}
		
	}
	
}
























































  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值