拼多多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;
}
}