拼多多2021笔试真题集

拼多多2021笔试真题集

数字组合

多多君最近在研究某种数字组合:
定义为:每个数字的十进制表示中(0~9),每个数位各不相同且各个数位之和等于N。
满足条件的数字可能很多,找到其中的最小值即可。
多多君还有很多研究课题,于是多多君找到了你–未来的计算机科学家寻求帮助。

要求最小:一定是第一位最小,剩下的按照…789排序
因为个数位各不相同所以n<=45

一位数最大为9,二位数最大为8+9=17依次
得出i位数最大i(18-i+1)/2
如果一个数是k位数,就是k-1位数中最大的加上最小的第k位数

import java.util.Scanner;
 
public class Main {
  public static void main(String[] args) {
    //
      Scanner in=new Scanner(System.in);
      int n=in.nextInt();
      if(n<=45){
          int i=0;
          //算出和为n的最大位数
          while(i*(18-i+1)/2<n){
              i++;
          }
          i--;
          //最小的第k位数
          System.out.print(n-i*(18-i+1)/2);
          for(int j=0;j<i;j++){
          	  //剩下的k-1位数按..789输出
              System.out.print(9-i+j+1);
          }
          System.out.println();
      }else{
          System.out.println(-1);
      }
  }
}

字符变换

多多君最近在研究字符串之间的变换,可以对字符串进行若干次变换操作:

交换任意两个相邻的字符,代价为0。
将任意一个字符a修改成字符b,代价为 |a - b|(绝对值)。

现在有两个长度相同的字符串X和Y,多多君想知道,如果要将X和Y变成两个一样的字符串,需要的最少的代价之和是多少

只有字符之间的变化:开两个int[26]将所有字符的个数存入

两个字符离得越近|a-b|越小,其实就是a到b的距离

如果是c->a,b->c这样交换,比起b->a,c->c多了两个bc的距离

在这里插入图片描述
所以可以知道,所有的线不能相交

import java.util.Scanner;
 
public class Main {
  public static void main(String[] args) {
    //
      Scanner in=new Scanner(System.in);
      int n=in.nextInt();
      String str1=in.next();
      String str2=in.next();
      int[] num1=new int[26];
      int[] num2=new int[26];
      for(int i=0;i<n;i++){
          num1[str1.charAt(i)-'a']++;
          num2[str2.charAt(i)-'a']++;
      }
      int i=0;
      int res=0;
      while(i<26){
          if(num1[i]==0){
              i++;
          }else{
              for(int j=0;j<26;j++){
                  if(num2[j]!=0){
                      res+=Math.abs(j-i);
                      num1[i]--;
                      num2[j]--;
                      break;
                  }
              }
          }
      }
      System.out.println(res);
  }
}

求和计算

多多路上从左到右有N棵树(编号1~N),其中第i个颗树有和谐值Ai。
多多鸡认为,如果一段连续的树,它们的和谐值之和可以被M整除,那么这个区间整体看起来就是和谐的。
现在多多鸡想请你帮忙计算一下,满足和谐条件的区间的数量。

令Si=a1+a2+…+ai;
新建一个mod数组第i位存储Si%M
如果mod[i]==mod[j]那么 (Sj-Si)%M=0 <=> i+1到j这一区间满足条件
结果是O(n²)复杂度过不去

那么只要有两个以上的mod值相同,
在mod值相同中任取两个都满足,既C ( 2 k ) \tbinom{2}{k} (k2)
那么只用在输入的时候更新mod值,再遍历mod值个数就达到O(nm)的复杂度了

import java.math.BigInteger;
import java.util.Scanner;
 
public class Main {
  public static void main(String[] args) {
    //
      Scanner in=new Scanner(System.in);
      int n=in.nextInt();
      int m=in.nextInt();
      int[] num=new int[n+1];
      long[] mod=new long[m];
      for(int i=1;i<=n;i++){
          num[i]=(num[i-1]+in.nextInt()%m)%m;
          mod[num[i]]++;
      }
      //这边怕超long因为最大可以达到2^n-1
      BigInteger res= BigInteger.valueOf(0);
      for(int i=0;i<m;i++){
          res=res.add(mod[i]<2?BigInteger.valueOf(0):BigInteger.valueOf(mod[i]*(mod[i]-1)/2));
      }
	  //记得加上mod[0],就是a1+...+ai%m=0同样满足
      System.out.println(res.add(BigInteger.valueOf(mod[0])).toString());
  }
}

骰子组合

多多君拼团购买了N个骰子,为了方便后面进行活动,多多君需要将这些骰子进行分类。
两个骰子为同类的定义是:

1将其中一个骰子通过若干次上下、左右或前后翻转后,其与另一个骰子对应的6面数字均相等。

现在多多君想知道不同种类的骰子的数量分别有多少。

其实就是所谓的错版
上下左右前后分别记作abcdef
只要固定两个方位,剩下4个也固定

那就要设计一套自己的规则
我的规则是

将数字为1的面朝上,那么ab固定
剩下四个最小的朝前,那么cdef固定
因为6个数各不相同,那就可以用字符串abcdef表示当前状态(伪状态压缩)
再用hashmap存储个数
因为结果要从大到小输出,转存到list里排序一下输出

import java.util.*;
 
public class Main {
  public static void main(String[] args) {
    //
      Scanner in=new Scanner(System.in);
      int n=in.nextInt();
      int a,b,c,d,e,f;
      HashMap<String,Integer> map=new HashMap<>();
      for(int i=0;i<n;i++){
          a=in.nextInt();
          b=in.nextInt();
          c=in.nextInt();
          d=in.nextInt();
          e=in.nextInt();
          f=in.nextInt();
          String str=roll(a,b,c,d,e,f);
          int k=0;
          if(map.containsKey(str)){
              k=map.get(str);
          }
          //存储个数
          map.put(str,k+1);
      }
      List<Integer> list=new ArrayList<>();
      for(String str:map.keySet()){
          list.add(map.get(str));
      }
      Collections.sort(list,(o1,o2)->o2-o1);
      System.out.println(list.size());
      for(int i=0;i<list.size();i++)
          System.out.print(list.get(i)+" ");
  }
  static String roll(int a,int b,int c,int d,int e,int f){
  	  //数字为1的面朝上
      if(a==1){}
      else if(b==1){
          b=a;a=1;int temp=c;c=d;d=temp;
      }else if(c==1){
          c=b;b=d;d=a;a=1;
      }else if(d==1){
          d=b;b=c;c=a;a=1;
      }else if(e==1){
          e=b;b=f;f=a;a=1;
      }else{
          f=b;b=e;e=a;a=1;
      }
      //剩下四个面最小的朝前
      if(c<d && c<e && c<f){
          int temp=c;c=f;f=d;d=e;e=temp;
      }else if(d<c && d<e && d<f){
          int temp=d;d=f;f=c;c=e;e=temp;
      }else if(e<d && e<c && e<f){}
      else if(f<c && f<d && f<e){
          int temp=f;f=e;e=temp;
          temp=c;c=d;d=temp;
      }
      //压缩状态
      return a+""+b+""+c+""+d+""+e+""+f;
  }
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值