题目## 题目
解题思路
这是一道关于多项式序列的题目。主要思路如下:
-
问题分析:
- 给定 k k k 个7次多项式,每个多项式只有两个非零系数
- 需要找到所有序列中第 n n n 小的数字
- 每个序列是将 n = 1 , 2 , 3... n=1,2,3... n=1,2,3... 代入多项式得到的值
-
优化思路:
- 使用优先队列维护 k k k 个序列的当前最小值
- 每次取出最小值后,将同一序列的下一个值加入队列
- 使用霍纳法则(Horner’s method)优化多项式计算
-
关键点:
- 使用小根堆维护当前最小值
- 记录每个序列的下一个位置
- 高效计算多项式值
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 8;
struct Node {
long value;
int id;
};
struct cmp {
bool operator()(const Node &a, const Node &b) {
return a.value > b.value;
}
};
// 使用霍纳法则计算多项式值
int compute(vector<int> &seq, int n) {
long ret = seq[0];
for(int i = 1; i < N; i++) {
ret = ret * n + seq[i];
}
return ret;
}
int main() {
int k = 0, n = 0;
scanf("%d", &k);
vector<vector<int>> seq(k, vector<int>(N, 0));
// 读入k个多项式的系数
for(int i = 0; i < k; i++) {
for(int j = 0; j < N; j++) {
scanf("%d", &seq[i][j]);
}
}
scanf("%d", &n);
// 初始化优先队列和每个序列的下一个位置
priority_queue<Node, vector<Node>, cmp> q;
vector<int> next(k, 1);
long val = 0;
// 将每个序列的第一个值加入队列
for(int i = 0; i < k; i++) {
val = compute(seq[i], next[i]);
q.push({val, i});
++next[i];
}
// 找第n小的数
while(--n) {
Node cur = q.top(); q.pop();
val = compute(seq[cur.id], next[cur.id]);
q.push({val, cur.id});
++next[cur.id];
}
cout << q.top().value << endl;
return 0;
}
import java.util.*;
public class Main {
static class Node {
long value;
int id;
Node(long value, int id) {
this.value = value;
this.id = id;
}
}
static long compute(int[] seq, int n) {
long ret = seq[0];
for(int i = 1; i < 8; i++) {
ret = ret * n + seq[i];
}
return ret;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int k = sc.nextInt();
int[][] seq = new int[k][8];
for(int i = 0; i < k; i++) {
for(int j = 0; j < 8; j++) {
seq[i][j] = sc.nextInt();
}
}
int n = sc.nextInt();
PriorityQueue<Node> pq = new PriorityQueue<>((a, b) ->
Long.compare(a.value, b.value));
int[] next = new int[k];
Arrays.fill(next, 1);
for(int i = 0; i < k; i++) {
long val = compute(seq[i], next[i]);
pq.offer(new Node(val, i));
next[i]++;
}
while(--n > 0) {
Node cur = pq.poll();
long val = compute(seq[cur.id], next[cur.id]);
pq.offer(new Node(val, cur.id));
next[cur.id]++;
}
System.out.println(pq.peek().value);
}
}
from heapq import heappush, heappop
def compute(seq, n):
ret = seq[0]
for i in range(1, 8):
ret = ret * n + seq[i]
return ret
k = int(input())
seq = []
for _ in range(k):
seq.append(list(map(int, input().split())))
n = int(input())
# 使用堆来维护最小值
heap = []
next_pos = [1] * k
# 初始化堆
for i in range(k):
val = compute(seq[i], next_pos[i])
heappush(heap, (val, i))
next_pos[i] += 1
# 找第n小的数
for _ in range(n-1):
val, idx = heappop(heap)
new_val = compute(seq[idx], next_pos[idx])
heappush(heap, (new_val, idx))
next_pos[idx] += 1
print(heap[0][0])
算法分析
- 时间复杂度:
O
(
n
log
k
)
\mathcal{O}(n\log k)
O(nlogk)
- 每次操作堆的时间为 log k \log k logk
- 需要进行 n n n 次操作
- 空间复杂度:
O
(
k
)
\mathcal{O}(k)
O(k)
- 优先队列存储 k k k 个元素
- 存储 k k k 个序列的下一个位置
解题思路
这是一道分班问题,主要思路如下:
-
问题分析:
- 一个大班要分成两个小班
- 每个小朋友可能不希望和某些人同班
- 需要判断是否能满足所有要求
- 本质是一个二分图染色问题
-
解决方案:
- 使用两个数组记录每个小朋友的分班情况
- 对于每个请求 ( a , b ) (a,b) (a,b),尝试将 a , b a,b a,b 分到不同班
- 如果发现冲突,则无法满足要求
- 贪心策略:遇到新的请求就立即分班
-
实现细节:
- 使用数组标记每个小朋友在不同班级的状态
- 0表示未分配,1表示不能在该班
- 处理每对不想同班的请求
代码
#include <iostream>
using namespace std;
int main() {
int first[10000] = {0}, second[10000] = {0};
int m, n; // m为总人数,n为请求数
cin >> m >> n;
for(int i = 0; i < n; i++) {
int a, b;
cin >> a >> b;
// 尝试将a分到第一班,b分到第二班
if(first[a] == 0 && second[b] == 0) {
first[b] = 1; // b不能进第一班
second[a] = 1; // a不能进第二班
}
// 尝试将a分到第二班,b分到第一班
else if(first[b] == 0 && second[a] == 0) {
first[a] = 1;
second[b] = 1;
}
else {
cout << "0" << endl; // 无法满足要求
return 0;
}
}
cout << "1" << endl; // 可以满足所有要求
return 0;
}
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int[] first = new int[10000];
int[] second = new int[10000];
int m = sc.nextInt(); // 总人数
int n = sc.nextInt(); // 请求数
for(int i = 0; i < n; i++) {
int a = sc.nextInt();
int b = sc.nextInt();
// 尝试将a分到第一班,b分到第二班
if(first[a] == 0 && second[b] == 0) {
first[b] = 1; // b不能进第一班
second[a] = 1; // a不能进第二班
}
// 尝试将a分到第二班,b分到第一班
else if(first[b] == 0 && second[a] == 0) {
first[a] = 1;
second[b] = 1;
}
else {
System.out.println("0"); // 无法满足要求
return;
}
}
System.out.println("1"); // 可以满足所有要求
sc.close();
}
}
def can_satisfy_requests(m: int, requests: list) -> bool:
first = [0] * 10000
second = [0] * 10000
for a, b in requests:
# 尝试将a分到第一班,b分到第二班
if first[a] == 0 and second[b] == 0:
first[b] = 1 # b不能进第一班
second[a] = 1 # a不能进第二班
# 尝试将a分到第二班,b分到第一班
elif first[b] == 0 and second[a] == 0:
first[a] = 1
second[b] = 1
else:
return False
return True
def main():
m = int(input())
n = int(input())
requests = []
for _ in range(n):
a, b = map(int, input().split())
requests.append((a, b))
print("1" if can_satisfy_requests(m, requests) else "0")
if __name__ == "__main__":
main()
算法及复杂度
- 算法:贪心
- 时间复杂度: O ( n ) \mathcal{O}(n) O(n) - n n n 为请求数量
- 空间复杂度: O ( m ) \mathcal{O}(m) O(m) - m m m 为总人数
1442

被折叠的 条评论
为什么被折叠?



