数组实现
插入
时间复杂度:
template<class T>
void Queue<T>::push(const T& theElement) {
if (full()) {
// 如果需要扩容
changeLength();
}
// 把元素 theElement 加入队列
// 元素只能插入到 1~MaxSize 范围内
rear = (rear + 1) % MaxSize;
queue[rear] = theElement;
}
删除
时间复杂度:
n 为删除后队列中剩余元素个数
最好的情况下(即未满不移动):
最坏的情况下(满了整体前移):
做成环后时间复杂度变为
此时下标变成
为防止队列空和队列满无法判断, 因此队列需要空出一位
template<class T>
void Queue<T>::pop() {
if (front == rear) {
throw "当前队列为空, 无法删除";
}
// 循环队列队首索引增加 1 再删除
// 因为 front 表示队首前一位的位置
front = (front + 1) % MaxSize;
queue[front].~T();
}
插入
当队列满的时候, 需要增大数组
// 循环队列数组扩容
template<class T>
void Queue<T>::changeLength() {
cout << "扩容中.." << endl;
T* newQueue = new T[2 * MaxSize]; // 分配新的数组空间
int start = (front + 1) % MaxSize; // 起始位置
if (start < 2) {
// 没有形成环, 也就是 front=0, 一直没有删除元素的情况
copy(queue + start, queue + start + MaxSize - 1, newQueue);
}
else {
// 队列形成环, 分成两段进行复制
// 上图的 A~B
copy(queue + start, queue + MaxSize, newQueue);
// 上图的 C~G
copy(queue, queue + rear + 1, newQueue + MaxSize - start);
}
// 设置新队列的首和尾的元素位置
front = 2 * MaxSize - 1;
rear = MaxSize - 2;
MaxSize *= 2; // 队列长度扩大两倍
delete[] queue;
queue = newQueue;
};
// 插入元素
template<class T>
void Queue<T>::push(const T& theElement) {
if (full()) {
// 如果需要扩容
changeLength();
}
// 把元素 theElement 加入队列
// 元素只能插入到 1~MaxSize 范围内
rear = (rear + 1) % MaxSize;
queue[rear] = theElement;
}
完整代码
#include<iostream>
using namespace std;
template<class T>
class Queue {
public:
Queue(int MaxQueueSize = 10);
~Queue() {
delete[] queue;
}
bool empty() const {
return front == rear;
}
bool full() const {
// 比如 MaxSize=10, 数组下标范围为 0~9
// front=0, rear=9 就表示队列满
return (rear + 1) % MaxSize == front;
}
T first() const; // 返回头元素
T end() const; // 返回尾元素
void push(const T& theElement); // 把元素加入队尾
void pop(); // 删除首元素
void changeLength(); // 队列扩容
private:
int front; // 队首
int rear; // 队尾
int MaxSize; // 队列容量
T* queue; // element array
};
// 构造函数
template<class T>
Queue<T>::Queue(int MaxQueueSize) {
MaxSize = MaxQueueSize + 1; // 数组留出一定空间
queue = new T[MaxSize];
front = rear = 0;
}
// 返回队首元素
template<class T>
T Queue<T>::first() const {
if (empty()) {
throw "当前队列为空";
}
return queue[(front + 1) % MaxSize];
}
// 返回队尾元素
template<class T>
T Queue<T>::end() const {
if (empty()) {
throw "当前队列为空";
}
return queue[rear];
}
// 循环队列数组扩容
template<class T>
void Queue<T>::changeLength() {
cout << "扩容中.." << endl;
T* newQueue = new T[2 * MaxSize]; // 分配新的数组空间
int start = (front + 1) % MaxSize; // 起始位置
if (start < 2) {
// 没有形成环
copy(queue + start, queue + start + MaxSize - 1, newQueue);
}
else {
// 队列形成环
copy(queue + start, queue + MaxSize, newQueue);
copy(queue, queue + rear + 1, newQueue + MaxSize - start);
}
// 设置新队列的首和尾的元素位置
front = 2 * MaxSize - 1;
rear = MaxSize - 2;
MaxSize *= 2; // 队列长度扩大两倍
delete[] queue;
queue = newQueue;
};
// 插入元素
template<class T>
void Queue<T>::push(const T& theElement) {
if (full()) {
// 如果需要扩容
changeLength();
}
// 把元素 theElement 加入队列
// 元素只能插入到 1~MaxSize 范围内
rear = (rear + 1) % MaxSize;
queue[rear] = theElement;
}
// 删除元素
template<class T>
void Queue<T>::pop() {
if (empty()) {
throw "当前队列为空, 无法删除";
}
// 循环队列队首索引增加 1 再删除
// 因为 front 表示队首前一位的位置
front = (front + 1) % MaxSize;
queue[front].~T();
}
int main() {
Queue<int> q(3);
q.push(10);
q.push(12);
cout << "队首元素" << q.first() << endl; // 10
cout << "队尾元素" << q.end() << endl; // 13
q.pop();
q.push(13);
q.push(15);
q.push(16);
cout << "队首元素" << q.first() << endl; // 12
cout << "队尾元素" << q.end() << endl; // 13
return 0;
}
链表实现
两种链接方向
方案(a) 更适合删除
插入
时间复杂度:
template<class T>
void linkedQueue<T>::push(const T& theElement) {
chainNode<T>* p = new chainNode<T>(theElement, NULL);
if (front) {
// 队列不为空时
rear->next = p;
rear = p;
}
else {
// 队列为空时
rear = front = p;
}
}
删除
时间复杂度:
方案(a)
template<class T>
void linkedQueue<T>::pop() {
if (empty()) {
throw "当前队列为空, 无法删除";
}
chainNode<T>* next = front->next; // 备份下一个节点
delete front; // 释放原队首的空间
front = next; // 确定新的队首
}
方案(b)
析构函数
时间复杂度:
template<class T>
linkedQueue<T>::~linkedQueue() {
chainNode<T>* next;
// 遍历整个链表释放信息
while (front) {
next = front->next;
delete front;
front = next;
}
}
完整代码
#include<iostream>
using namespace std;
template <class T>
struct chainNode {
// 数据成员
T element;
chainNode<T>* next;
// 方法
chainNode() { }
chainNode(const T& element) {
this->element = element;
}
chainNode(const T& element, chainNode<T>* next) {
this->element = element;
this->next = next;
}
};
template<class T>
class linkedQueue {
public:
linkedQueue() {
// 初始化时指向 NULL
front = rear = NULL;
}
~linkedQueue();
bool empty() const {
// 判断队首是不是指向 NULL
return front ? false : true;
}
T first() const; // 返回头元素
T end() const; // 返回尾元素
void push(const T& theElement); // 把元素加入队尾
void pop(); // 删除首元素
private:
chainNode<T>* front;
chainNode<T>* rear;
};
// 析构函数
template<class T>
linkedQueue<T>::~linkedQueue() {
chainNode<T>* next;
// 遍历整个链表释放信息
while (front) {
next = front->next;
delete front;
front = next;
}
}
// 返回队首元素
template<class T>
T linkedQueue<T>::first() const {
if (empty()) {
throw "当前队列为空";
}
return front->element;
}
// 返回队尾元素
template<class T>
T linkedQueue<T>::end() const {
if (empty()) {
throw "当前队列为空";
}
return rear->element;
}
// 插入元素
template<class T>
void linkedQueue<T>::push(const T& theElement) {
chainNode<T>* p = new chainNode<T>(theElement, NULL);
if (front) {
// 队列不为空时
rear->next = p;
rear = p;
}
else {
// 队列为空时
rear = front = p;
}
}
// 删除元素
template<class T>
void linkedQueue<T>::pop() {
if (empty()) {
throw "当前队列为空, 无法删除";
}
chainNode<T>* next = front->next; // 备份下一个节点
delete front; // 释放原队首的空间
front = next; // 确定新的队首
}
int main() {
linkedQueue<int> q;
q.push(10);
q.push(12);
cout << "队首元素" << q.first() << endl; // 10
cout << "队尾元素" << q.end() << endl; // 13
q.pop();
q.push(13);
q.push(15);
q.push(16);
cout << "队首元素" << q.first() << endl; // 12
cout << "队尾元素" << q.end() << endl; // 13
return 0;
}
车厢重排
与栈实现刚好相反, 车厢号数大的可以入队, 车厢号数小的只能去其他队列
- 3, 6, 9 依次入队
- 2 比 9 小, 入另一个队
- 1 符合条件, 直接出轨, 符合条件的车厢变成 2 号, 2 号出队, 符合条件的车厢变成 3 号, 如此反复...
代码实现
#include<iostream>
#include<queue>
#include<vector>
using namespace std;
class Rearrange {
public:
Rearrange(int numberOfTracks) {
this->numberOfTracks = numberOfTracks;
track = new queue<int>[numberOfTracks + 1];
smallestCar = INT_MAX; // 表示一个不存在车厢
itsTrack = -1;
}
bool putInHoldingTrack(int);
void outputFromHoldingTrack(vector<int>*);
vector<int> railroad(vector<int>);
private:
int numberOfTracks; // 缓冲轨道数
// 队列中最小车厢号
// 初始值是一个不存在的车厢号, 表示轨道中没有车
int smallestCar;
int itsTrack; // 最小车厢号所在队列号
queue<int>* track; // 车厢队列
};
// 为车厢 c 寻找最适合的缓冲轨道
bool Rearrange::putInHoldingTrack(int c) {
int bestTrack = 0, // 目前最合适的缓冲轨道
bestLast = 0; // 队尾车厢最接近 c 的车厢号
// 扫描缓冲轨道
for (int i = 1; i <= numberOfTracks;i++) {
if (!track[i].empty()) {
// 缓冲轨道 i 不空
int lastCar = track[i].back(); // 获取队尾元素
// 取最接近 c 的最大车厢号所在队列作为最合适缓冲轨道
if (c > lastCar && lastCar > bestLast) {
// 缓冲轨道 i 的尾部具有编号更大的车厢
bestLast = lastCar;
bestTrack = i;
}
}
else {
// 缓冲轨道 i 为空, 则最佳轨道就是 i
if (bestTrack == 0) bestTrack = i;
}
}
if (bestTrack == 0) return false; // 没有可用的缓冲轨道
// 把车厢 c 移到最佳缓冲轨道 bestTrack
track[bestTrack].push(c);
// 更新 smallestCar 和 itsTrack
if (c < smallestCar) {
smallestCar = c;
itsTrack = bestTrack;
}
return true;
}
void Rearrange::outputFromHoldingTrack(vector<int>* r) {
track[itsTrack].pop(); // 从队列删除编号最小的车厢
r->push_back(smallestCar); // 输出轨道
// 更新最小车厢号数和队列号
smallestCar = INT_MAX;
for (int i = 1; i <= numberOfTracks; i++) {
if (!track[i].empty() && track[i].front() < smallestCar) {
smallestCar = track[i].front();
itsTrack = i;
}
}
}
vector<int> Rearrange::railroad(vector<int> cars) {
int nextCarToOutput = 1; // 符合出轨条件的车厢号(即第一个是 1 号车厢)
int numberOfCars = cars.size(); // 车厢数
vector<int> res;
for (int i = 0; i < numberOfCars; i++) { // 遍历所有车厢
if (cars[i] == nextCarToOutput) {
// 符合出轨条件, 车厢出轨
res.push_back(cars[i]);
nextCarToOutput++; // 符合条件的车厢+1(车厢号数只会是连续的)
while (smallestCar == nextCarToOutput) {
// 一旦有车厢出轨, 则从缓冲轨道中陆续取出车厢
// 只有缓冲轨道中最小车厢号 smallestCar 符合出轨条件才能 output
outputFromHoldingTrack(&res);
nextCarToOutput++;
}
}
else {
// 如果找不到合适的缓冲轨道, 说明排序失败
if (!putInHoldingTrack(cars[i])) {
throw "排序失败";
}
}
}
return res;
}
int main() {
vector<int> cars = { 3, 6, 9, 2, 4, 7, 1, 8, 5 };
Rearrange r(3);
cars = r.railroad(cars);
for (int i = 0; i < cars.size(); i++) {
cout << cars[i] << " ";
}
return 0;
}
电路布线
即寻找两点间最短路径问题
从 a 开始, 其相邻格子标记为 1, 1 的相邻格子标记为 2, 以此类推, 直到 b 被标记, 其编号就是最短距离
步骤
- 从 start 开始遍历, 给其周围的 4 个可达节点标记为 1, 标记的同时入队
- 如果存在终点, 则结束, 不存在终点, 将标记为 1 的节点出队, 然后访问其 4 个可达节点, 以此类推
- 如果访问到的可达结点为终点, 退出循环
- 队列为空且最终未达终点, 则终点不可达
代码实现
广度优先搜索, 回溯法
#include<iostream>
#include<queue>
#include<vector>
using namespace std;
// 坐标类
class Point {
public:
int x;
int y;
Point(int x, int y) {
this->x = x;
this->y = y;
}
Point() {} // 什么都不做的构造函数
};
vector<Point> findPath(Point start, Point end, vector<vector<int>> grid) {
vector<Point> path; // 最短路径数组
int pathLength; // 最短路径长度
// 寻找从始点到终点的最短路径
if ((start.x == end.x) && (start.y == end.y)) { // 始点 = 终点
pathLength = 0;
return path;
}
// 初始化偏移量
Point offset[4] = {
Point(0, 1), // 右
Point(1, 0), // 下
Point(0, -1), // 左
Point(-1, 0), // 上
};
int numOfNbrs = 4; // 一个方格最多 4 个相邻位置
queue<Point> q; // 节点队列
Point nbr; // 一个临时节点
Point cur = start; // 表示当前方块
// start 周围 4 个方格会先入队
// 然后先出队去找 4 个节点的可达节点
do {
// 给相邻位置做标记
for (int i = 0; i < numOfNbrs; i++) {
// 检查相邻位置
nbr.x = cur.x + offset[i].x;
nbr.y = cur.y + offset[i].y;
if (nbr.x < 0 || nbr.x > 6 || nbr.y < 0 || nbr.y > 6) {
continue;
}
if (grid[nbr.x][nbr.y] == 0) { // 可标记
grid[nbr.x][nbr.y] = grid[cur.x][cur.y] + 1; // 相邻位置的编号多 1
if (nbr.x == end.x && nbr.y == end.y) break; // 标记完成
// 把相邻位置入队
q.push(nbr);
}
}
// 是否到达终点
if ((nbr.x == end.x) && (nbr.y == end.y)) break; // 到达
// 没到终点, 判断队列是否为空
if (q.empty()) return path; // 路径不存在
cur = q.front(); // 取下一个位置
q.pop();
} while (true);
// 构造路径, 路径长度为终点编号 - 3(即去掉起始和终点, 且起始点起始编号为 2)
pathLength = grid[end.x][end.y] - 3;
cout << "终点编号" << grid[end.x][end.y] << endl;
cout << "最短路径长度: " << pathLength << endl;
path.resize(pathLength);
// 从终点回溯
cur = end;
for(int j = pathLength - 1; j >= 0; j--) {
for (int i = 0; i < numOfNbrs; i++) {
nbr.x = cur.x + offset[i].x;
nbr.y = cur.y + offset[i].y;
if (nbr.x < 0 || nbr.x > 6 || nbr.y < 0 || nbr.y > 6) continue;
// 编号小一位就找到了祖先节点
if (grid[nbr.x][nbr.y] == j + 3) break;
}
cur = nbr; // 移向祖先
path[j] = cur; // 寻找祖先位置
}
return path;
}
int main() {
// 起始位置标记为 2
vector<vector<int>> grid = {{0, 0, 1, 0, 0, 0, 0 },
{0, 0, 1, 1, 0, 0, 0 },
{0, 2, 0, 0, 1, 0, 0 },
{0, 0, 0, 1, 1, 0, 0 },
{1, 0, 0, 0, 1, 0, 0 },
{1, 1, 1, 0, 0, 0, 0 },
{1, 1, 1, 0, 0, 0, 0 }};
Point start(2, 1);
Point end(3, 5);
vector<Point> p = findPath(start, end, grid);
cout << "路径为: (" << start.x << "," << start.y << ")-";
for (int i = 0; i < p.size(); i++) {
cout << "(" << p[i].x << "," << p[i].y << ")-";
}
cout << "(" << end.x << "," << end.y << ")" << endl;
return 0;
}
杨辉三角
杨辉三角与组合数
由上图可知, 杨辉三角第 n 行的其实是 的系数, 下方的值是上方左右两个值相加(边界的 1 可以理解为+0)
#include<iostream>
#include<queue>
using namespace std;
void YANGVI(int n) {
queue<int> yang; // 队列初始化
cout << 1 << endl; // 第一行
// 第二行的两个数据数据
yang.push(1);
yang.push(1);
int s = 0;
for (int i = 1; i < n; i++) {
yang.push(0); // 0 作为一行结束
for (int j = 1; j <= i + 2; j++) {
int t = yang.front(); // 读取上方右边的值
yang.pop();
// s 代表上方左边的值
yang.push(s + t); // 计算下一行系数, 并进队列
s = t;
// 一行要执行 i+2 次循环
// 第 i+2 次是取出末尾的 0, 加上前面的 1 作为下一行结束的 1
// 并且 0 还可以在下一次循环时加上第一个 1 作为开头的 1
if (j != i + 2) cout << s << " ";
}
cout << endl;
}
}
int main() {
YANGVI(10);
return 0;
}
上面的队列还保留着 n+1 行的数据(这可以用于计算最终多项式的表达式)
非队列方案
vector<vector<int>> generate(int numRows) {
vector<vector<int>> arr = {{1}}; // 第一个是 1
for(int i = 1; i < numRows; i++) {
int j = 0;
vector<int> list;
while(j <= i) {
if(j - 1 < 0 || j == i) {
// 第一个和最后一个都是 1
list.push_back(1);
} else {
list.push_back(arr[i - 1][j - 1] + arr[i - 1][j]);
}
j++;
}
arr.push_back(list);
}
return arr;
}
动态规划法
#include<vector>
#include<iostream>
using namespace std;
vector<int> getRow(int rowIndex) {
vector<int> ans(rowIndex + 1, 1);
// 第 0 层和第 1 层都是 1, 因此从第 2 层开始
for (int i = 2; i < ans.size(); i++) {
for (int j = i - 1; j > 0; j--) {
// 从后往前修改, 这样不会影响下一次计算
ans[j] = ans[j] + ans[j - 1];
}
}
return ans;
};
vector<vector<int>> getYangVi(int num) {
vector<vector<int>> ans;
for (int i = 0; i < num; i++) {
ans.push_back(getRow(i));
}
return ans;
}
int main() {
vector<vector<int>> res = getYangVi(6);
for (int i = 0; i < res.size(); i++) {
for (int j = 0; j < res[i].size(); j++) {
cout << res[i][j] << " ";
}
cout << endl;
}
return 0;
}
类杨辉三角与多项式
由上图可知, 下方的值等于上方“左×b的系数+右×a的系数”
#include <iostream>
#include<string>
#include <queue>
using namespace std;
// (na+mb)^exp
string polynomial(int n, int m, int exp) {
queue <int> q;
q.push(n);
q.push(m);
// 类似杨辉三角
int s = 0, t;
for (int i = 1; i < exp; i++) {
q.push(0);
for (int j = 1; j <= i + 2; j++) {
t = q.front();
q.pop();
// b 的系数 × 左上 + a 的系数 × 右上
q.push(n * t + m * s);
s = t;
}
}
int a = exp, b = 0; // 这是 a 和 b 在表达式中的指数
bool first = true; // 这代表当前是否为第一项
string expr; // 表达式
while (!q.empty()) {
int coefficient = q.front(); // 系数
q.pop();
if (coefficient == 0) {
a--;
b++;
continue;
};
if (!first && coefficient > 0) {
// 第一个项, 不需要加号
// 系数大于 0 才需要 + 号
// 因为 - 号会跟着系数带上
expr += "+";
}
if (coefficient != 1 && coefficient != -1) {
expr += to_string(coefficient);
}
else if (coefficient == -1) {
expr += "-";
}
if (a != 0 && a != 1) {
expr += ("x^" + to_string(a));
}
else if (a == 1) {
expr += "x";
}
if (b != 0 && b != 1) {
expr += ("y^" + to_string(b));
}
else if (b == 1) {
expr += "y";
}
a--;
b++;
first = false;
}
return expr;
}
int main() {
int n, m, e;
cin >> n >> m >> e;
cout << polynomial(n, m, e);
// 2 3 2
// 4x^2+12xy+9y^2
return 0;
}
注意系数如果太大的话, int 队列就不行了
大整数
如果 a 和 b 的系数很大(-1000~1000), 指数 exp 也很大(2~20), 那么 long long 根本不够用!
思路: 转成字符串计算
完整代码
#include<iostream>
#include<queue>
#include<string>
using namespace std;
class Solution {
public:
// 获取绝对值
string absolute(string num) {
if (num[0] == '-') {
return num.substr(1);
}
return num;
}
// 字符串乘法
string multiply(string num1, string num2) {
bool negative; // 是否是负数
if (num1[0] == '-' && num2[0] == '-') {
// 两个负数相乘, 等于正数
negative = false;
}
else if (num1[0] == '-' || num2[0] == '-') {
// 只要有一个为负数, 结果就为负数
negative = true;
}
else {
// 两个都是正数的情况
negative = false;
}
// 数字字符串取绝对值运算
num1 = absolute(num1);
num2 = absolute(num2);
int n1 = num1.size(),
n2 = num2.size();
// 初始化一个全 0 字符串
// 两个数相乘, 其结果的位数不会超过两者位数之和
string res(n1 + n2, '0');
int length, start;
length = start = n1 + n2 - 1;
// 从后往前遍历
for (int j = n2 - 1; j >= 0; j--) {
int k = start;
int carry = 0; // 进位
for (int i = n1 - 1; i >= 0; i--) {
// 两数相乘 + 进位 + 上一轮此位置结果
int sum = (num2[j] - '0') * (num1[i] - '0') + carry + (res[k] - '0');
carry = sum / 10;
res[k] = (sum % 10 + '0');
k--;
}
if (carry) {
/* 最终进位
* 该位置一定没有被占用过
* 1 2 5
* × 8 9
* -------------------
* (进位) 9 18 45
* (进位) 8 16 40
*/
res[k] = carry + '0';
}
start--;
}
// 获取第一个不为 0 的下标
int k = 0;
while (k <= length && res[k] == '0') {
k++;
}
if (k == length + 1) return "0"; // 结果为 0
// 去除字符串 res 前面的 0
res = res.substr(k);
if (negative) {
// 负数
return '-' + res;
}
return res;
}
// 字符串加法(仅支持非负数)
string add(string num1, string num2) {
int n1 = num1.size(),
n2 = num2.size();
// 两数相加, 最多不超过最大数位数 + 1
int len = n1 > n2 ? n1 + 1: n2 + 1;
string res(len, '0');
// 数字字符串补 0
num1 = string(len - n1, '0') + num1;
num2 = string(len - n2, '0') + num2;
int carry = 0; // 进位
int k = len - 1; // 开始的位置
for (int i = len - 1; i > 0; i--) {
int sum = (num2[i] - '0') + (num1[i] - '0') + carry;
carry = sum / 10;
res[k] = (sum % 10 + '0');
k--;
}
if (carry) {
res[k] = carry + '0';
}
// 去掉前面的 0
if (res[0] == '0') {
return res.substr(1);
}
return res;
}
/*
* 判断两个数谁大(仅支持非负数)
* 返回 true, 当且仅当 num1 大
*/
bool less(string num1, string num2) {
// 字符串长度大的表示数大
int n1 = num1.size(),
n2 = num2.size();
// 长度一样, 直接比较字符串
if (n1 == n2) return num1 > num2;
// 长度大的数大
return n1 > n2;
}
// 字符串减法(仅支持非负数)
string sub(string num1, string num2) {
int n1 = num1.size(),
n2 = num2.size();
string res;
if (less(num1, num2)) {
// num1 更大, 可以直接做减法
res = subtract(num1, num2);
}
else {
// num1 小, 用 num2 - num1 后加上负号
res = '-' + subtract(num2, num1);
}
return res;
}
// 减法, 要求 num1 > num2(仅支持非负数)
string subtract(string num1, string num2) {
int n1 = num1.size(),
n2 = num2.size();
// 两数相减, 结果的位数不会超过最大位
int len = n1 > n2 ? n1: n2;
string res(len, '0');
// 数字字符串补 0
num1 = string(len - n1, '0') + num1;
num2 = string(len - n2, '0') + num2;
int borrow = 0; // 借位
for (int k = len - 1; k >= 0; k--) {
int z = (num1[k] - borrow - num2[k] + 10) % 10;
res[k] = z + '0';
borrow = num1[k] - borrow - num2[k] < 0 ? 1 : 0;
}
int pos = 0;
while (pos <= len && res[pos] == '0') {
pos++;
}
return res.substr(pos);
}
};
string polynomial(int n, int m, int exp) {
queue<string> q;
Solution sol;
// 系数转字符串
string a = to_string(n);
string b = to_string(m);
q.push(a);
q.push(b);
string num1, num2;
string ans;
string s = "0", t;
// 这一步和普通写法相似, 只不过换成字符串加减法
for (int i = 1; i < exp; i++) {
q.push("0");
for (int j = 1; j <= i + 2; j++) {
t = q.front();
q.pop();
num1 = sol.multiply(t, a);
num2 = sol.multiply(s, b);
if (num1[0] == '-' && num2[0] == '-') {
// 两个都是负数, 取绝对值后相加, 再加个负号
ans = '-' + sol.add(sol.absolute(num1), sol.absolute(num2));
}
else if (num1[0] == '-') {
// num1 是负数, 则 num2 肯定不是
// num2 - |num1|
ans = sol.sub(num2, sol.absolute(num1));
}
else if (num2[0] == '-') {
// 能判断到这里, 说明 num1 不是负数, num2 是负数
ans = sol.sub(num1, sol.absolute(num2));
}
else {
// 都不是负数, 直接相加
ans = sol.add(num1, num2);
}
q.push(ans);
s = t;
}
}
int ac = exp, bc = 0; // 这是 a 和 b 在表达式中的指数
bool first = true; // 这代表当前是否为第一项
string expr; // 表达式
while (!q.empty()) {
string coefficient = q.front(); // 系数
q.pop();
if (coefficient == "0") {
ac--;
bc++;
continue;
};
if (!first && coefficient[0] != '-') {
// 第一个项, 不需要加号
// 系数大于 0 才需要 + 号
// 因为 - 号会跟着系数带上
expr += "+";
}
if (coefficient != "1" && coefficient != "-1") {
expr += coefficient;
}
else if (coefficient == "-1") {
expr += "-";
}
if (ac != 0 && ac != 1) {
expr += ("x^" + to_string(ac));
}
else if (ac == 1) {
expr += "x";
}
if (bc != 0 && bc != 1) {
expr += ("y^" + to_string(bc));
}
else if (bc == 1) {
expr += "y";
}
ac--;
bc++;
first = false;
}
return expr;
}
int main() {
int n, m , e;
cin >> n >> m >> e;
cout << polynomial(n, m, e);
return 0;
}