騰訊2018秋招筆試真題(1)
騰訊2018秋招筆試真題
小Q的歌單
【題目描述】小 Q 有 X 首長度為 A 的不同的歌和 Y 首長度為 B 的不同的歌,現在小 Q 想用這些歌組成一個
總長度正好為 K 的歌單,每首歌最多隻能在歌單中出現一次,在不考慮歌單內歌曲的先後順序的情況下,
請問有多少種組成歌單的方法。
輸入描述:
每個輸入包含一個測試用例。
每個測試用例的第一行包含一個整數,表示歌單的總長度 K(1<=K<=1000)。
接下來的一行包含四個正整數,分別表示歌的第一種長度 A(A<=10)和數量 X(X<=100)以及歌的第二種長度
B(B<=10)和數量 Y(Y<=100)。保證 A 不等於 B。
輸出描述:
輸出一個整數,表示組成歌單的方法取模。因為答案可能會很大,輸出對 1000000007 取模的結果。
輸入示例:
5
2 3 3 3
輸出示例:
9
解題思路:
x首歌裡面取i首,每首歌長度為A
y首歌裡面取j首歌,每首歌長度為B
加起來長度為K
i*A + j*B = K
有多少種方式,可看成排列組合來做
類比(有一個盒子中裝有紅球x個,白球y個,取出紅球得A分,取出白球得B分,從中任意取使得得到的分數為K分,有多少種方法)
滿足條件
0 <= i <= x
j = (K-i*A)/B <= y
(K-i*A)%B = 0
import java.util.Scanner;
public class Main01 {
public static void main(String[] args) {
int [][] c = new int[101][101];//組合排列
Scanner in = new Scanner(System.in);
int K = in.nextInt(); //歌單總長度
int A = in.nextInt(); //第一種歌的長度
int x = in.nextInt(); //第一種歌的數量
int B = in.nextInt(); //第二種歌的長度
int y = in.nextInt(); //第二種歌的數量
//初始化陣列c 第一個引數是下標, 第二個引數是上標
c[0 ][0] = 1;
for(int i = 1; i < c.length; i++) {
c[i][0] = 1;
for(int j = 1; j < c[0].length; j++) {
c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % 1000000007;
}
}
int res = 0;
for(int i = 0; i <= x; i++) { //i首長度為A的歌
if(i * A <= K && (K - i * A) % B == 0 && (K - i * A) / B <= y) {
res = (res + ((c[x][i] * c[y][(K-(i * A)) / B])) % 1000000007 ) % 1000000007;
}
}
System.out.println(res);
}
}
安排機器
【題目描述】小 Q 的公司最近接到 m 個任務, 第 i 個任務需要 xi 的時間去完成, 難度等級為 yi。
小 Q 擁有 n 臺機器, 每臺機器最長工作時間 zi, 機器等級 wi。
對於一個任務,它只能交由一臺機器來完成, 如果安排給它的機器的最長工作時間小於任務需要的時間,
則不能完成,如果完成這個任務將獲得 200 * xi + 3 * yi 收益。
對於一臺機器,它一天只能完成一個任務, 如果它的機器等級小於安排給它的任務難度等級, 則不能完成。
小 Q 想在今天儘可能的去完成任務, 即完成的任務數量最大。如果有多種安排方案,小 Q 還想找到收益最大
的那個方案。小 Q 需要你來幫助他計算一下。
輸入描述:
輸入包括 N + M + 1 行,
輸入的第一行為兩個正整數 n 和 m(1 <= n, m <= 100000), 表示機器的數量和任務的數量。
接下來 n 行,每行兩個整數 zi 和 wi(0 < zi < 1000, 0 <= wi <= 100), 表示每臺機器的最大工作時間和
機器等級。
接下來的 m 行,每行兩個整數 xi 和 yi(0 < xi < 1000, 0 <= yi<= 100), 表示每個任務需要的完成時間和
任務的難度等級。
輸出描述:
輸出兩個整數, 分別表示最大能完成的任務數量和獲取的收益。
輸入示例:
1 2
100 3
100 2
100 1
輸出示例:
1 20006
解題思路:
對2個佇列分別進行排序
排序規則為:先按time從大到小排,再按level從大到小排(因為時間佔收益的比重比較大,所以優先time排序)
然後處理任務進行匹配
匹配規則為:選擇機器時間>=任務時間,機器優先順序與任務優先順序最接近的
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
class Task implements Comparable {
int time; //時間
int level; //等級
public Task(int time, int level) {
super();
this.time = time;
this.level = level;
}
@Override
public int compareTo(Object o) {
Task t = (Task)o;
if(this.time > t.time) {
return -1;//返回-1,表示當前物件在前,即從大到小排序
} else if(this.time < t.time) {
return 1;
} else {
if(this.level > t.level) {
return -1;
} else {
return 1;
}
}
}
}
public class Main02 {
public static void main(String[] args) {
List<Task> machine = new ArrayList<Task>();
List<Task> job = new ArrayList<Task>();
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int m = in.nextInt();
for(int i = 0; i < n; i++) {
Task t = new Task(in.nextInt(), in.nextInt());
machine.add(t);
}
for(int j = 0; j < m; j++) {
Task t = new Task(in.nextInt(), in.nextInt());
job.add(t);
}
Collections.sort(machine);
Collections.sort(job);
int count = 0;
int sum = 0;
int[] mark = new int[101];
for(int i = 0, j = 0; i < m; i++) {//m項任務
while(j < n && machine.get(j).time >= job.get(i).time) {
//由於從大到小排序,所以如果machine.time比位於前面的job.time大,那也比後面的大,後面只需要比較優先順序
mark[machine.get(j).level]++;
j++;
}
for(int k = job.get(i).level; k <= 100; k++) {
if(mark[k] != 0) {//mark[k]=1時表示優先順序為k的機器可以處理該任務
count++;
sum += 200 * job.get(i).time + 3 * job.get(i).level;
mark[k]--;
break;
}
}
}
System.out.println(count + " " + sum);
}
}