4.20日美团后端笔试编程题解

4.20日美团后端笔试编程题解

第一个编程题。
题目
给定输入N,n,m,p;
N为数组A的长度,
p是A[1]的值,数组每项的值都是通过前一项来确定的,关系式如下
A[x]=(A[x-1]+153)%p;
n,m是n*m对数据,要求求他们每一对的最大公约数,以该公约数数为下标获得数组中的相应值,然后进行求和,最后获得最终值。
第一题的n,m,让你在1到n,1到m各选一个数字(也就是说你要选择n*m对数字),求得最大公约数后,把结果当作下标,然后求和(sum += A[最大公约数])。
由于第一题在笔试过程中未能AC(题意真的很模糊的了),因此以下解法不一定是AC解法,欢迎大家拿AC代码分享。

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

public class GcdTrue {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int bign=sc.nextInt();
        int n=sc.nextInt();
        int m=sc.nextInt();
        int p=sc.nextInt();
        int A[]=new int[bign+1];
        A[1]=p;
        for(int x=2;x1;x++){
            A[x]=(A[x-1]+153)%p;
        }
        int sum=0;
        for(int a=1;a<=n;a++){
            for(int b=1;b<=m;b++){
                sum=sum+A[gcd(a,b)];
                /*
                 * BigInteger tmp1=new BigInteger(Integer.toString(a));
                 * BigInteger tmp2=new BigInteger(Integer.toString(b));
                 * sum=sum+A[(tmp1.gcb(tmp2)).intvalue()];
                 */
            }
        }


        System.out.println(sum);
        sc.close();
    }
    public static int gcd(int a,int b){//辗转相初法返回最大公约数
        if(b==0){
            return a;
        }
        return gcd(b,a%b);
    }
}

引申,最大公约数和最小公倍数的计算`

public class GcdAndLcm {
    public static void main(String[] args) {
        System.out.println(gcd(222,407));
        System.out.println(gcd(407,222));
        System.out.println(lcm(407,222));
    }
    public static int gcd(int a,int b){//辗转相除法返回最大公约数
        if(b==0){
            return a;
        }
        return gcd(b,a%b);
    }
    public static int lcm(int a,int b){//两数之积除以最大公约数就是最小公倍数
        return a*b/gcd(a,b);
    }
}

第二题
输入,首个输入是要计算的组数T,后面有t个输入,计算每个输入对应的数的位数之和。
例如,如果输入为2 4 13
2指接下来有两个输入,
4指从1-4所有数字的位数,即1234,因此输出为4。
13指1-13所有数字的位数,即12345678910111213,因此输出为17。
思路是搞明白输入是一个几位数,就能够计算出相应的输出。
从正面来思考的话,我想到想要知道是一个几位数,只需要知道它能够除的最大的10的N次方即可得到结果大于等于1,反推回去的话就是每除以一个10得到的结果大于1等于,就证明它的位数增加1。
以这个思路来做,每除以10得到结果大于等于1,就把对应少1位的数的位数全部加上,然后计算保持最大位数的数有多少个(即该数+1-最大位数的最小值)。
过程中需要的变量包括,
count,记录能除几个10,结果+1就是最高位位数。初始值为0
sum,动态记录结果值。初始值为0
more,最高位数的数的个数。
以110为例。
110/10=11>1,
此时因为除以1个10之后大于1,我能够知道最少是一个2位数,记录一下count,将它+1,然后sum=sum+9*count*10的count-1次方。因为1位数有9个,2位数有90个,3位数有900个,以此类推,所以每当确定它包含了某位数之后,就将对应的位数添加上。这里sum=0+9*1*1=9;
然后再让11/10=1(整除),
因为整除第二个10后等于1,可以知道最少是一个三位数,count++,sum=sum+9*count*10的count-1次方=9+9*2*10=189;
1/10=0<1,
此时由于小于1,我们可以知道它就是一个三位数,此时一位数和二位数的位数都已经被我们加在sum中了,只需要看有多少个三位数即可。
三位数从100开始,到该值结束,因此是more=该值-99=110-100+1=11,也就是说有11个三位数我们还没有计算进sum中,此时让sum=sum+more*(count+1)=189+11*(2+1)=189+33=222,sum就是我们要求的值了,输出即可。

import java.util.Scanner;

public class Count {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int t=sc.nextInt();
        int a[]=new int[t];
        for(int i=0;idouble sum=0;
        for(int i=0;iint count=0;
            int tmp=a[i];
            while(tmp/10>=1){
                count++;
                sum=sum+9*Math.pow(10, count-1)*count;
                tmp=tmp/10;
            }
            double more=a[i]+1-Math.pow(10, count);
            sum=sum+more*(count+1);
            long longsum=(long)sum;
            System.out.println(longsum);
            sum=0;
        }
        sc.close();
    }
}

第二题是笔试过程中的AC代码,有些同学可能会在过程中没考虑到数的范围,在笔试过程中int和long的区别还是相当大的,之前的360笔试就是吃了这个亏了。以后碰到得多加注意。


欢迎交流,以上仅供参考,有自己的思考才能有进步。

你可能感兴趣的:(笔试整理,笔试,美团,编程,gcd与lcm,辗转相除法)