第一题 多多的数字组合
多多君最近在研究某种数字组合:
定义为:每个数字的十进制表示中(0~9),每个数位各不相同且各个数位之和等于N。
满足条件的数字可能很多,找到其中的最小值即可。
输入描述:
共一行,一个正整数N,如题意所示,表示组合中数字不同数位之和。
(1 <= N <= 1,000)
输出描述:
共一行,一个整数,表示该组合中的最小值。
如果组合中没有任何符合条件的数字,那么输出-1即可。
输入例子1:
5
输出例子1:
5
例子说明1:
符合条件的数字有:5,14,23,32,41
其中最小值为5
要求整理:每个数位不同,且和等于N,取组合最小值 数位共1-9,要求组合最小,所以不考虑0,并且低位用当前可用的最大数。 并且1+2+…+9
= 45,所以如果大于45可以直接返回-1。 每次都用最大的数,可以从9开始一直到1。
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
int num = scan.nextInt();
int ans = 0, max = 9, level = 1;
if(num > 45)System.out.println(-1);
else{
while(num > 0){
if(num > max){
ans += max * level;
level *= 10;
}else ans += num *level;
num -= max;
max--;
}
System.out.println(ans);
}
}
}
多多的字符变换
多多君最近在研究字符串之间的变换,可以对字符串进行若干次变换操作:
交换任意两个相邻的字符,代价为0。
将任意一个字符a修改成字符b,代价为 |a – b|(绝对值)。
现在有两个长度相同的字符串X和Y,多多君想知道,如果要将X和Y变成两个一样的字符串,需要的最少的代价之和是多少。
输入描述:
共三行,第一行,一个整数N,表示字符串的长度。
(1 <= N <= 2,000)
接下来两行,每行分别是一个字符串,表示字符串X和Y。
(字符串中仅包含小写字母)
输出描述:
共一行,一个整数,表示将X和Y变换成一样的字符串需要的最小的总代价。
输入例子1:
4
abca
abcd
输出例子1:
3
例子说明1:
其中一种代价最小的变换方案:
都修改为abcd,那么将第一个字符串X最后一个字符a修改为d,代价为|a – d| = 3。
要求整理:将 x 变为 y 的最小代价,交换字符消耗 0 ,改变字符消耗 | x – y |
x = a,s1 ; y = s2,a,s3 ; // si为任意字符串
可将 y 中 a 交换一直移到 y = a,s2,s3;
x 与 y 比较 =》s1 与 s2,s3比较
同理可将相同字符移到相同位置
故代价最小的字符变换可等价于寻找 x 与 y 的不同字符代价最小的变换
直接将输入字符串散列到数组中,然后对修改消耗进行累加。
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
int len = scan.nextInt(), i = 0, j = 0, count = 0;
scan.nextLine();
String s1 = scan.nextLine();
String s2 = scan.nextLine();
//得到对应字母个数
int[] ch1 = new int[26];
int[] ch2 = new int[26];
for(i = 0 ; i < len ; i++){
ch1[s1.charAt(i)-'a']++;
ch2[s2.charAt(i)-'a']++;
}
i = 0;
while(i < 26 && j < 26){
if(ch1[i] > ch2[j]){
count += ch2[j] * Math.abs(i-j);
ch1[i] -= ch2[j];
do{ j++;}while(j < 26 && ch2[j] == 0);
}else if(ch1[i] < ch2[j]){
count += ch1[i] * Math.abs(i-j);
ch2[j] -= ch1[i];
do{ i++;}while(i < 26 && ch1[i] == 0);
}else{
count += ch1[i] * Math.abs(i-j);
do{ j++;}while(j < 26 && ch2[j] == 0);
do{ i++;}while(i < 26 && ch1[i] == 0);
}
}
System.out.println(count);
}
}
多多的求和计算
多多路上从左到右有N棵树(编号1~N),其中第i个颗树有和谐值Ai。
多多鸡认为,如果一段连续的树,它们的和谐值之和可以被M整除,那么这个区间整体看起来就是和谐的。
输入描述:
第一行,有2个整数N和M,表示树的数量以及计算和谐值的参数。
( 1 <= N <= 100,000, 1 <= M <= 100 )
第二行,有N个整数Ai, 分别表示第i个颗树的和谐值。
( 0 <= Ai <= 1,000,000,000 )
输出描述:
共1行,每行1个整数,表示满足整体是和谐的区间的数量。
输入例子1:
5 2
1 2 3 4 5
输出例子1:
6
例子说明1:
长度为1: [2], [4]
长度为2: 无
长度为3: [1,2,3], [3,4,5]
长度为4: [1,2,3,4], [2,3,4,5]
长度为5: 无
共6个区间的和谐值之和可以被2整除。
要求整理:Ai <= 1,000,000,000 ; 1 <= N <= 100,000;故判断时不能直接累加。
因为区间和可以被 2 整除为和谐,可以被 M 整除等价于 num & M == 0。
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int N = scan.nextInt(), M = scan.nextInt(), count = 0;
int[] arr = new int[N];
for(int i = 0 ; i < N ; i++){
int num = scan.nextInt();
if(num >= M)arr[i] = num % M;
else arr[i] = M;
}
for(int i = 0 ; i < N ; i++){
int sum = arr[i];
if(sum == 0){
count++;
}
for(int j = i+1 ; j < N ; j++){
sum += arr[j];
if(sum >= M)sum = sum % M;
if(sum == 0){
count++;
}
}
}
System.out.println(count);
}
}
时间复杂度为O(N2),不能完全ac。
多多的骰子组合
两个骰子为同类的定义是:
将其中一个骰子通过若干次上下、左右或前后翻转后,其与另一个骰子对应的6面数字均相等。
输入描述:
第一行1个整数N,表示骰子的数量。
(1 <= N <= 1,000)
接下来N行,每行6个数字(1~6,且各不相同)
其中第i行表示第i个骰子当前上、下、左、右、前、后这6面的数字。
输出描述:
共2行:
第一行1个整数M,表示不同种类的骰子的个数
第二行M个整数,由大到小排序,表示每个种类的骰子的数量
输入例子1:
2
1 2 3 4 5 6
1 2 6 5 3 4
输出例子1:
1
2
例子说明1:
第二个骰子相当于是第一个骰子从左向右旋转了一面得到,属于同类。
袁华:这道题太难了!!!太难了!!!我不会!!!(雪花飘飘T T)