声明
题解包含以下内容:
- (相对)高级的 C++ 模板及语法技巧
- 仅适用于 C++20 标准的代码
- 强烈的个人代码风格和 Modern C++ 范式追求
- 泛滥的标准库函数
换句话说就是(相较于其他公开题解)更低的查重率和更高的使用门槛;请酌情使用。
【id:79】【20分】A. 分数的加减乘除(运算符重载)
题目描述
Fraction类的基本形式如下:
// 定义Fraction类
class Fraction
{
private:
int fz, fm;
int commonDivisor(); // 计算最大公约数
void contracted(); // 分数化简
public:
Fraction(int = 0, int = 1);
Fraction(Fraction&);
Fraction operator+(Fraction);
Fraction operator-(Fraction);
Fraction operator*(Fraction);
Fraction operator/(Fraction);
void set(int = 0, int = 1);
void disply();
};
要求如下:
1.实现Fraction类;common_divisor()和contracted()函数体可为空,不实现具体功能。
2.编写main函数,初始化两个Fraction对象的,计算它们之间的加减乘除。
输入
第1行:依次输入第1个和第2个Fraction对象的分子和分母值。
输出
每行依次分别输出加减乘除计算后的Fraction对象(直接输出分数值,不需要约简)。
样例
输入样例1 | 输出样例1 |
---|---|
1 3 2 5 | fraction=11/15 fraction=-1/15 fraction=2/15 fraction=5/6 |
Answer
#include <bits/stdc++.h>
using namespace std;
class Fraction {
int fz, fm;
int commonDivisor() const {
return std::gcd( abs( fz ), abs( fm ) );
}
void contracted() {
if ( auto gcd_num = commonDivisor();
gcd_num >= 1 ) {
fz /= gcd_num;
fm /= gcd_num;
}
if ( fm < 0 && fz > 0 ) {
fz *= -1;
fm = abs( fm );
} else if ( fz < 0 && fm < 0 ) {
fz = abs( fz );
fm = abs( fm );
}
}
public:
Fraction( int _fz = 0, int _fm = 1 )
: fz { _fz }, fm { _fm } {}
Fraction( const Fraction& lhs ) {
fz = lhs.fz;
fm = lhs.fm;
}
Fraction operator+( Fraction& lhs ) {
contracted(); lhs.contracted();
return Fraction( fz * lhs.fm + fm * lhs.fz, fm * lhs.fm );
}
Fraction operator-( Fraction& lhs ) {
contracted(); lhs.contracted();
return Fraction( fz * lhs.fm - fm * lhs.fz, fm * lhs.fm );
}
Fraction operator*( Fraction& lhs ) {
contracted(); lhs.contracted();
return Fraction( fz * lhs.fz, fm * lhs.fm );
}
Fraction operator/( Fraction& lhs ) {
contracted(); lhs.contracted();
return Fraction( fz * lhs.fm, fm * lhs.fz );
}
void set( int _fz = 0, int _fm = 1 ) {
fz = _fz; fm = _fm;
contracted();
}
void disply() const {
cout << "fraction="sv << fz << "/" << fm << endl;
}
friend istream& operator>>( istream& is, Fraction& lhs ) {
is >> lhs.fz >> lhs.fm;
lhs.contracted();
return is;
}
};
int main()
{
Fraction a1, a2;
cin >> a1 >> a2;
(a1 + a2).disply();
(a1 - a2).disply();
(a1 * a2).disply();
(a1 / a2).disply();
}
【id:80】【20分】B. 复数的加减乘运算(运算符重载)
题目描述
定义一个复数类,通过重载运算符:+、-、*,实现两个复数之间的各种运算。
class Complex
{
private:
float real, image;
public:
Complex(float x = 0, float y = 0);
friend Complex operator+(Complex&, Complex&);
friend Complex operator-(Complex&, Complex&);
friend Complex operator*(Complex&, Complex&);
void show();
};
要求如下:
1.实现Complex类;
2.编写main函数,初始化两个Complex对象,计算它们之间的加减乘,并输出结果。
复数相乘的运算规则
设z1=a+bi,z2=c+di(a、b、c、d∈R)是任意两个复数,那么它们的积(a+bi)(c+di)=(ac-bd)+(bc+ad)i.
输入
第1行:输入两个数值,分别为第一个Complex对象的实部和虚部。
第2行:输入两个数值,分别为第二个Complex对象的实部和虚部。
输出
第1行:两个Complex对象相加后的输出结果。
第2行:两个Complex对象相减后的输出结果。
第3行:两个Complex对象相乘后的输出结果。
样例
输入样例1 | 输出样例1 |
---|---|
10 20 50 40 | Real=60 Image=60 Real=-40 Image=-20 Real=-300 Image=1400 |
Answer
#include <bits/stdc++.h>
using namespace std;
class Complex {
double real, image;
public:
Complex( double x = {}, double y = {} )
: real { x }, image { y } {}
friend Complex operator+( const Complex& a, const Complex& b ) {
return Complex( a.real + b.real, a.image + b.image );
}
friend Complex operator-( const Complex& a, const Complex& b ) {
return Complex( a.real - b.real, a.image - b.image );
}
friend Complex operator*( const Complex& a, const Complex& b ) {
return Complex( a.real * b.real - a.image * b.image, a.real * b.image + a.image * b.real );
}
void show() const {
cout << fixed << setprecision(0) << "Real="sv << real << " Image="sv << image << endl;
}
friend istream& operator>>( istream& is, Complex& cc ) {
return is >> cc.real >> cc.image;
}
};
int main()
{
Complex c1, c2;
cin >> c1 >> c2;
(c1 + c2).show();
(c1 - c2).show();
(c1 * c2).show();
}
【id:94】【20分】C. 向量的加减(运算符重载)
题目描述
设向量X=(x1,x2,…,xn)和Y=(y1,y2…,yn),它们之间的加、减分别定义为:
X+Y=(x1+y1,x2+y2,…,xn+yn)
X-Y=(x1-y1,x2-y2,…,xn-yn)
编程序定义向量类Vector ,重载运算符“+”、“-”,实现向量之间的加、减运算;并编写print函数作为向量的输出操作。
Vector类的基本形式如下:
class Vector
{
private:
int vec[5];
public:
Vector(int v[]);
Vector();
Vector(const Vector& obj);
Vector operator +(const Vector& obj);
Vector operator -(const Vector& obj);
void print();
};
要求如下:
1.实现Vector类;
2.编写main函数,初始化两个Vector对象的,计算它们之间的加减,并输出结果。
输入
第1行:输入5个int类型的值,初始化第一个Vector对象。
第2行: 输入5个int类型的值,初始化第二个Vector对象。
输出
第1行:2个Vector对象相加后的输出结果。
第2行:2个Vector对象相减后的输出结果。
样例
输入样例1 | 输出样例1 |
---|---|
-4 1 0 10 5 -11 8 10 17 -6 | -15 9 10 27 -1 7 -7 -10 -7 11 |
Answer
#include <bits/stdc++.h>
using namespace std;
class Vector {
std::array<int, 5> vec;
public:
explicit Vector( std::array<int, 5> v )
: vec { move( v ) } {}
Vector() {}
Vector( const Vector& obj ) : Vector( obj.vec ) {}
Vector operator+( const Vector& obj ) const {
Vector ret = *this;
for ( size_t i = 0; i < ret.vec.size(); ++i )
ret.vec[i] += obj.vec[i];
return ret;
}
Vector operator-( const Vector& obj ) const {
Vector ret = *this;
for ( size_t i = 0; i < ret.vec.size(); ++i )
ret.vec[i] -= obj.vec[i];
return ret;
}
void print() const {
for ( int e : vec )
cout << e << ' ';
cout << endl;
}
friend istream& operator>>( istream& is, Vector& v ) {
for ( auto& e : v.vec )
is >> e;
return is;
}
};
int main()
{
Vector v1, v2;
cin >> v1 >> v2;
( v1 + v2 ).print();
( v1 - v2 ).print();
}
【id:83】【20分】D. 矩阵相乘(运算符重载)
题目描述
定义一个矩阵类MyMatrix,并且在类中进行运算符重定义,用*实现矩阵相乘。要求必须对运算符进行重载,如果用函数如multiply(matrix,matrix)去实现矩阵之间的运算一律记0分。
必须包含以下析构函数,其中n是矩阵的阶数,data是存放矩阵数据的二维动态数组:
MyMatrix::~MyMatrix() { // 释放空间 for (int i = 0; i < n; i++) { delete[] data[i]; } delete[] data; }
输入
第一行输入所需要的矩阵个数c;
第二行输入矩阵的阶数n,即矩阵是一个n*n的矩阵;
第三行开始依次输入c个矩阵.
输出
c个矩阵相乘的结果
样例
输入样例1 | 输出样例1 |
---|---|
2 2 1 2 1 2 1 0 1 1 | 3 2 3 2 |
Answer
#include <bits/stdc++.h>
using namespace std;
class MyMatrix {
int **data;
size_t size;
void kill_data() {
if ( data != nullptr ) {
for ( size_t i = 0; i < size; ++i )
delete[] data[i];
delete[] data;
} else size = 0;
}
public:
MyMatrix() : data { nullptr }, size {} {}
MyMatrix( size_t s ) : MyMatrix() {
data = new int*[s] {};
for ( size_t i = 0; i < s; ++i )
data[i] = new int[s] {};
size = s;
}
MyMatrix( const MyMatrix& other ) : MyMatrix() {
data = new int*[other.size];
for ( size_t i = 0; i < other.size; ++i ) {
data[i] = new int[other.size] {};
memcpy( data[i], other.data[i], other.size * sizeof( int ) );
}
size = other.size;
}
MyMatrix( MyMatrix&& rhs ) : MyMatrix() {
using std::swap;
swap( data, rhs.data );
swap( size, rhs.size );
}
~MyMatrix() {
kill_data();
}
MyMatrix operator*( const MyMatrix& other ) {
MyMatrix ret( this->size );
for ( size_t i = 0; i < size; ++i ) {
memset( ret.data[i], 0, ret.size * sizeof( int ) );
for ( size_t ii = 0; ii < size; ++ii ) {
for ( size_t iii = 0; iii < size; ++iii )
ret.data[i][ii] += data[i][iii] * other.data[iii][ii];
}
}
return ret;
}
MyMatrix& operator=( const MyMatrix& other ) {
if ( other.size == 0 )
return *this;
kill_data();
data = new int*[other.size];
for ( size_t i = 0; i < other.size; ++i ) {
data[i] = new int[other.size] {};
memcpy( data[i], other.data, other.size * sizeof( int ) );
}
size = other.size;
return *this;
}
MyMatrix& operator=( MyMatrix&& rhs ) {
using std::swap;
swap( data, rhs.data );
swap( size, rhs.size );
return *this;
}
friend istream& operator>>( istream& is, MyMatrix& m ) {
for ( size_t i = 0; i < m.size; ++i ) {
for ( size_t ii = 0; ii < m.size; ++ii )
is >> m.data[i][ii];
}
return is;
}
friend ostream& operator<<( ostream& os, const MyMatrix& m ) {
for ( size_t i = 0; i < m.size; ++i ) {
for ( size_t ii = 0; ii < m.size; ++ii )
os << m.data[i][ii] << ( ii < m.size - 1 ? " " : "" );
os << ( i < m.size - 1 ? "\n" : "" );
}
return os;
}
};
int main()
{
size_t c {}, n {};
cin >> c >> n;
--c;
MyMatrix ret( n );
cin >> ret;
while ( c-- ) {
MyMatrix tmp( n );
cin >> tmp;
ret = ret * tmp;
}
cout << ret << endl;
}
【id:342】【20分】E. 最小生日差值计算(运算符重载)
题目描述
定义一个学生类Student,包含该学生的姓名、出生年、月、日 ,重定义 “-”号实现两个学生之间相差多少天的比较。并利用重载的“-”运算符,求所有学生中年龄相差最小的两个人的名字以及相差天数。
输入
第一行:输入所需要输入的学生个数;
第二行开始,依次输入每个学生的姓名、出生年、月、日。
输出
输出年龄相差最小的两个人的名字以及相差天数,名字的输出顺序按输入的先后,天数大于等于0。
样例
输入样例1 | 输出样例1 |
---|---|
3 Tom 1995 1 1 Joe 1995 2 28 Jimmy 1996 1 8 | Tom和Joe年龄相差最小,为58天。 |
Answer
#include <bits/stdc++.h>
using namespace std;
class Date {
int32_t year;
int16_t month, day;
static constexpr int16_t base_year = 1970;
static constexpr std::array<int8_t, 12> months = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
static bool is_leap( int yy ) {
return (yy % 4 == 0 && yy % 100 != 0) || yy % 400 == 0;
}
int count() const {// 返回当前日期是今年第几天
return accumulate( months.begin(), months.begin() + (month - 1), day ) + (month > 2 ? is_leap(year) : 0);
}
public:
Date( int32_t yy, int16_t mm, int16_t dd )
: year { yy }, month { mm }, day { dd } {}
Date() : Date( {}, {}, {} ) {}
int32_t operator-( const Date& d ) const {
int32_t this_days = count(), d_days = d.count();
for ( int32_t i = base_year; i < year; ++i )
this_days += 365 + is_leap( i );
for ( int32_t i = base_year; i < d.year; ++i )
d_days += 365 + is_leap( i );
return this_days - d_days;
}
auto operator<=>( const Date& d ) const {
if ( d.year == year )
if ( d.month == month )
return d.day <=> day;
else return d.month <=> month;
else return d.year <=> year;
}
friend istream& operator>>( istream& is, Date& d ) {
return is >> d.year >> d.month >> d.day;
}
};
class Student {
string name;
Date birthday;
public:
Student( string nm, Date birth )
: name { move( nm ) }, birthday { move( birth ) } {}
Student() : Student( {}, {} ) {}
int operator-( const Student& s ) const {
return birthday - s.birthday;
}
const string& get_name() const { return name; }
auto operator<=>( const Student& s ) const {
return birthday <=> s.birthday;
}
friend istream& operator>>( istream& is, Student& s ) {
return is >> s.name >> s.birthday;
}
};
int main()
{
#ifdef _WIN32
system( "chcp 65001" );
#endif
size_t num {}; cin >> num;
vector<Student> students;
unordered_map<string, size_t> input_order;
for ( size_t i = 0; i < num; ++i ) {
Student s; cin >> s;
input_order.insert( make_pair( s.get_name(), i ) );
students.push_back( move( s ) );
}
sort( students.begin(), students.end() );
auto stu_pair = make_pair( students.begin(), students.begin() );
int32_t diff = INT32_MAX;
for ( auto iter = students.begin() + 1; iter != students.end(); ++iter ) {
if ( auto tmp_diff = abs( *iter - *prev( iter ) );
tmp_diff < diff ) {
tie( stu_pair.first, stu_pair.second, diff ) = make_tuple( prev( iter ), iter, tmp_diff );
}
}
if ( input_order[stu_pair.first->get_name()] > input_order[stu_pair.second->get_name()] ) {
using std::swap;
swap( stu_pair.first, stu_pair.second );
}
cout << stu_pair.first->get_name() << "和"
<< stu_pair.second->get_name() << "年龄相差最小,为"
<< diff << "天。\n";
}