声明
题解包含以下内容:
- (相对)高级的 C++ 模板及语法技巧
- 仅适用于 C++20 标准的代码
- 强烈的个人代码风格和 Modern C++ 范式追求
- 泛滥的标准库函数
换句话说就是(相较于其他公开题解)更低的查重率和更高的使用门槛;请酌情使用。
【id:112】【20分】A. 向量1(类和对象)
题目描述
n个有序数a1,a2,…,an组成的数组称为n维向量。 为n维向量定义CVector类,包含私有数据成员:
int *data;//存储n维向量
int n; //向量维数。
方法有:
(1)无参构造函数,设置n=5,data的数据分别为0,1,2,3,4;
(2)构造函数,用虚参n1和数组a初始化n和data的数据;
(3)输出函数,按格式输出n维向量的值;
(4)析构函数。
主函数输入数据,生成CVector对象并调用输出函数测试。
输入
输入n
输入n维向量
输出
分别调用无参和带参构造函数生成2个CVector对象,输出它们的值。
样例
输入样例1 | 输出样例1 |
---|---|
6 10 1 2 3 4 5 | 0 1 2 3 4 10 1 2 3 4 5 |
Answer
#include <bits/stdc++.h>
using namespace std;
inline int __init_arr[5] = { 0, 1, 2, 3, 4 };
class CVector {
static int sum;
int* data;
int n;
public:
static int get_sum() { return sum; }
static void reset_sum() { sum = 0; }
CVector( int nn, const int* dat )
: data { nullptr }, n { nn } {
data = new int[n] {};
memcpy( data, dat, n * sizeof( int ) );
}
CVector( const CVector& lhs )
: CVector( lhs.n, lhs.data ) {}
CVector( CVector&& rhs ) {
data = rhs.data;
rhs.data = nullptr;
n = rhs.n;
}
CVector() : CVector( 5, __init_arr ) {}
~CVector() { delete[] data; }
void print() const {
if ( data == nullptr ) return;
for ( size_t i = 0; i < static_cast<size_t>(n); ++i )
cout << (i != 0 ? " " : "") << data[i];
cout << endl;
}
void scanner( int nn ) {
if ( n != nn ) {
n = nn; delete[] data;
data = new int [n] {};
}
for ( size_t i = 0; i < static_cast<size_t>(n); ++i )
cin >> data[i];
sum += accumulate( data, data + n, 0 );
}
float Average() const {
return accumulate( data, data + n, 0.0f ) / n;
}
friend ostream& operator<<( ostream& os, const CVector& v ) {
if ( v.data == nullptr ) return os;
for ( size_t i = 0; i < static_cast<size_t>(v.n); ++i )
os << (i != 0 ? " " : "") << v.data[i];
return os;
}
friend CVector add( const CVector& v1, const CVector& v2 ) {
if ( v1.n != v2.n ) return {};
auto ret = v1;
transform( v2.data, v2.data + v2.n, v1.data, ret.data, plus<int>() );
return ret;
}
};
int CVector::sum = 0;
int main()
{
int n {}; cin >> n;
CVector v1, v2;
v2.scanner( n );
cout << v1 << endl
<< v2 << endl;
}
【id:113】【20分】B. 向量2(友元及拷贝构造)
题目描述
在题目向量1的代码上添加类CVector的友元函数add,计算两个向量的和(对应分量相加)。
add定义如下:
CVector add(const CVector v1, const CVector v2) //函数头不可修改。
主函数输入数据,生成两个向量对象v1,v2,调用add(v1, v2).print()输出向量v1 + v2的计算结果。(假设print()为CVector类中的输出函数。)
可根据需要,为类CVector添加拷贝构造函数及其它成员函数。
输入
第一行,输入测试次数t
每组测试数据格式如下:
向量维数n
第一个n维向量值
第二个n维向量值
输出
对每组测试数据,输出两个n维向量与它们的和
样例
输入样例1 | 输出样例1 |
---|---|
2 3 1 2 3 4 5 6 5 1 2 3 4 5 -1 2 4 6 10 | 1 2 3 4 5 6 5 7 9 1 2 3 4 5 -1 2 4 6 10 0 4 7 10 15 |
Answer
#include <bits/stdc++.h>
using namespace std;
inline int __init_arr[5] = { 0, 1, 2, 3, 4 };
class CVector {
static int sum;
int* data;
int n;
public:
static int get_sum() { return sum; }
static void reset_sum() { sum = 0; }
CVector( int nn, const int* dat )
: data { nullptr }, n { nn } {
data = new int[n] {};
memcpy( data, dat, n * sizeof( int ) );
}
CVector( const CVector& lhs )
: CVector( lhs.n, lhs.data ) {}
CVector( CVector&& rhs ) {
data = rhs.data;
rhs.data = nullptr;
n = rhs.n;
}
CVector() : CVector( 5, __init_arr ) {}
~CVector() { delete[] data; }
void print() const {
if ( data == nullptr ) return;
for ( size_t i = 0; i < static_cast<size_t>(n); ++i )
cout << (i != 0 ? " " : "") << data[i];
cout << endl;
}
void scanner( int nn ) {
if ( n != nn ) {
n = nn; delete[] data;
data = new int [n] {};
}
for ( size_t i = 0; i < static_cast<size_t>(n); ++i )
cin >> data[i];
sum += accumulate( data, data + n, 0 );
}
float Average() const {
return accumulate( data, data + n, 0.0f ) / n;
}
friend ostream& operator<<( ostream& os, const CVector& v ) {
if ( v.data == nullptr ) return os;
for ( size_t i = 0; i < static_cast<size_t>(v.n); ++i )
os << (i != 0 ? " " : "") << v.data[i];
return os;
}
friend CVector add( const CVector& v1, const CVector& v2 ) {
if ( v1.n != v2.n ) return {};
auto ret = v1;
transform( v2.data, v2.data + v2.n, v1.data, ret.data, plus<int>() );
return ret;
}
};
int CVector::sum = 0;
int main()
{
size_t t {}; cin >> t;
while ( t-- ) {
int n {}; cin >> n;
CVector v1, v2;
v1.scanner( n );
v2.scanner( n );
cout << v1 << endl
<< v2 << endl
<< add( v1, v2 ) << endl;
}
}
【id:114】【20分】C. 向量3(静态成员)
题目描述
为向量1题目实现的CVector类添加私有静态成员sum,在初始化对象的同时,统计所有对象的n维向量和sum。
主函数生成多个对象,测试向量和。
可根据需要自行添加需要的静态成员函数,添加非静态成员函数不得分。
输入
测试次数t
每组测试数据格式如下:
输入m,表示n维向量的数目
后跟m行,每行格式:向量维数n n维向量值
输出
对每组测试数据的m个向量,输出所有向量的分量和sum
样例
输入样例1 | 输出样例1 |
---|---|
2 2 5 1 2 3 4 5 3 4 5 6 3 2 1 2 3 10 20 30 2 11 22 | 1 2 3 4 5 4 5 6 30 1 2 10 20 30 11 22 96 |
Answer
#include <bits/stdc++.h>
using namespace std;
inline int __init_arr[5] = { 0, 1, 2, 3, 4 };
class CVector {
static int sum;
int* data;
int n;
public:
static int get_sum() { return sum; }
static void reset_sum() { sum = 0; }
CVector( int nn, const int* dat )
: data { nullptr }, n { nn } {
data = new int[n] {};
memcpy( data, dat, n * sizeof( int ) );
}
CVector( const CVector& lhs )
: CVector( lhs.n, lhs.data ) {}
CVector( CVector&& rhs ) {
data = rhs.data;
rhs.data = nullptr;
n = rhs.n;
}
CVector() : CVector( 5, __init_arr ) {}
~CVector() { delete[] data; }
void print() const {
if (data == nullptr) return;
for ( size_t i = 0; i < static_cast<size_t>(n); ++i )
cout << (i != 0 ? " " : "") << data[i];
cout << endl;
}
void scanner( int nn ) {
if ( n != nn ) {
n = nn; delete[] data;
data = new int [n] {};
}
for ( size_t i = 0; i < static_cast<size_t>(n); ++i )
cin >> data[i];
sum += accumulate( data, data + n, 0 );
}
float Average() const {
return accumulate( data, data + n, 0.0f ) / n;
}
friend ostream& operator<<( ostream& os, const CVector& v ) {
if ( v.data == nullptr ) return os;
for ( size_t i = 0; i < static_cast<size_t>(v.n); ++i )
os << (i != 0 ? " " : "") << v.data[i];
return os;
}
friend CVector add( const CVector& v1, const CVector& v2 ) {
if ( v1.n != v2.n ) return {};
auto ret = v1;
transform( v2.data, v2.data + v2.n, v1.data, ret.data, plus<int>() );
return ret;
}
};
int CVector::sum = 0;
int main()
{
size_t t {}; cin >> t;
while ( t-- ) {
int m {}; cin >> m;
while ( m-- ) {
int n {}; cin >> n;
CVector v {};
v.scanner( n );
cout << v << endl;
}
cout << CVector::get_sum() << endl;
CVector::reset_sum();
}
}
【id:115】【20分】D. 向量4(类复合)
题目描述
为向量1题目中实现的CVector类增加成员函数float Average(),计算n维向量的平均值并返回。
定义CStudent类,私有数据成员为:
string name; // 姓名
CVector score; // n个成绩
(1)添加构造函数,用虚参name1、n1、数组a1初始化CStudent类对象。
(2)添加输出函数,按样例格式输出CStudent对象值。
主函数输入数据,测试CStudent对象。
输入
输入多行,每行格式为:学生姓名 科目n n个成绩
输出
对每行测试数据,生成学生对象,输出如下数据:
学生姓名 n个成绩 成绩的平均值(保留2位小数)
样例
输入样例1 | 输出样例1 |
---|---|
wangwu 5 90 80 70 100 90 lisi 3 100 90 100 | wangwu 90 80 70 100 90 86.00 lisi 100 90 100 96.67 |
Answer
#include <bits/stdc++.h>
using namespace std;
inline int __init_arr[5] = { 0, 1, 2, 3, 4 };
class CVector {
static int sum;
int* data;
int n;
public:
static int get_sum() { return sum; }
static void reset_sum() { sum = 0; }
CVector( int nn, const int* dat )
: data { nullptr }, n { nn } {
data = new int[n] {};
memcpy( data, dat, n * sizeof( int ) );
}
CVector( const CVector& lhs )
: CVector( lhs.n, lhs.data ) {}
CVector( CVector&& rhs ) {
data = rhs.data;
rhs.data = nullptr;
n = rhs.n;
}
CVector() : CVector( 5, __init_arr ) {}
~CVector() { delete[] data; }
void print() const {
if ( data == nullptr ) return;
for ( size_t i = 0; i < static_cast<size_t>(n); ++i )
cout << (i != 0 ? " " : "") << data[i];
cout << endl;
}
void scanner( int nn ) {
if ( n != nn ) {
n = nn; delete[] data;
data = new int [n] {};
}
for ( size_t i = 0; i < static_cast<size_t>(n); ++i )
cin >> data[i];
sum += accumulate( data, data + n, 0 );
}
float Average() const {
return accumulate( data, data + n, 0.0f ) / n;
}
friend ostream& operator<<( ostream& os, const CVector& v ) {
if ( v.data == nullptr ) return os;
for ( size_t i = 0; i < static_cast<size_t>(v.n); ++i )
os << (i != 0 ? " " : "") << v.data[i];
return os;
}
friend CVector add( const CVector & v1, const CVector & v2 ) {
if ( v1.n != v2.n ) return {};
auto ret = v1;
transform( v2.data, v2.data + v2.n, v1.data, ret.data, plus<int>() );
return ret;
}
friend istream& operator>>( istream& is, CVector& v ) {
int nn {}; is >> nn;
if ( v.n != nn ) {
v.n = nn; delete[] v.data;
v.data = new int [v.n] {};
}
for ( size_t i = 0; i < static_cast<size_t>(v.n); ++i )
is >> v.data[i];
sum += accumulate( v.data, v.data + v.n, 0 );
return is;
}
};
int CVector::sum = 0;
class CStudent {
string name;
CVector score;
public:
CStudent( string name1, int n1, const int* a1 )
: name { move( name ) }, score { n1, a1 } {}
CStudent( string name1, CVector score1 )
: name { move( name1 ) }, score { move( score1 ) } {}
CStudent() : CStudent( {}, {} ) {}
void print() const {
cout << name << ' '
<< score << ' '
<< fixed << setprecision( 2 )
<< score.Average() << endl;
}
friend ostream& operator<<( ostream& os, const CStudent& lhs ) {
return os << lhs.name << ' '
<< lhs.score << ' '
<< fixed << setprecision( 2 )
<< lhs.score.Average() << endl;
}
friend istream& operator>>( istream& is, CStudent& lhs ) {
return is >> lhs.name >> lhs.score;
}
};
int main()
{
CStudent stu;
while ( cin >> stu )
cout << stu;
}
【id:116】【20分】E. 向量5(友元类)
题目描述
(1)在向量CVector类的代码上,定义n阶矩阵类CMatrix,包含私有数据成员data存储矩阵数据,n存储矩阵阶数。
(2)将CMatrix定义为CVector的友元类。
(3)为CMatrix添加成员函数:CVector multi(const CVector &v1),计算n阶矩阵与n维向量v1的乘积。
(4)为CMatrix添加成员函数,判定矩阵与向量v1是否可计算乘积。
(5)为CMatrix添加需要的构造函数、析构函数和其它成员函数。
主函数输入数据,测试矩阵与向量的乘积。
动态创建n阶矩阵示例代码如下:
int n;
int** data;
int i, j;
cin >> n;
// 先创建n行
data = new int* [n];
// 再创建n列
for (i = 0; i < n; i++)
{
data[i] = new int[n];
}
// 写入矩阵
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
cin >> data[i][j];
}
}
输入
测试次数t
对每组测试数据,格式如下
第一行,矩阵阶数n
n阶矩阵
向量维数m
m维向量
输出
对每组测试数据,若矩阵与向量不能计算乘积,输出error;否则输出计算结果
样例
输入样例1 | 输出样例1 |
---|---|
1 3 1 0 0 0 1 0 0 0 1 3 1 2 3 | 1 2 3 |
Answer
#include <bits/stdc++.h>
using namespace std;
inline int __init_arr[5] = { 0, 1, 2, 3, 4 };
class CMatrix;
class CVector {
static int sum;
int* data;
int n;
public:
static int get_sum() { return sum; }
static void reset_sum() { sum = 0; }
CVector( int nn, const int* dat )
: data { nullptr }, n { nn } {
data = new int[n] {};
memcpy( data, dat, n * sizeof( int ) );
}
CVector( const CVector& lhs )
: CVector( lhs.n, lhs.data ) {}
CVector( CVector&& rhs ) {
data = rhs.data;
rhs.data = nullptr;
n = rhs.n;
}
CVector() : CVector( 5, __init_arr ) {}
~CVector() { delete[] data; }
void print() const {
if ( data == nullptr ) return;
for ( size_t i = 0; i < static_cast<size_t>(n); ++i )
cout << (i != 0 ? " " : "") << data[i];
cout << endl;
}
void scanner( int nn ) {
if ( n != nn ) {
n = nn; delete[] data;
data = new int [n] {};
}
for ( size_t i = 0; i < static_cast<size_t>(n); ++i )
cin >> data[i];
sum += accumulate( data, data + n, 0 );
}
float Average() const {
return accumulate( data, data + n, 0.0f ) / n;
}
CVector& operator=( const CVector& lhs ) {
if ( this != &lhs ) {
delete[] data; n = lhs.n;
data = new int[n] {};
memcpy( data, lhs.data, n * sizeof( int ) );
}
return *this;
}
CVector& operator=( CVector&& lhs ) {
if ( this != &lhs ) {
delete[] data;
n = lhs.n;
data = lhs.data;
lhs.data = nullptr;
}
return *this;
}
friend ostream& operator<<( ostream& os, const CVector& v ) {
if ( v.data == nullptr ) return os;
for ( size_t i = 0; i < static_cast<size_t>(v.n); ++i )
os << (i != 0 ? " " : "") << v.data[i];
return os;
}
friend CVector add( const CVector& v1, const CVector& v2 ) {
if ( v1.n != v2.n ) return {};
auto ret = v1;
transform( v2.data, v2.data + v2.n, v1.data, ret.data, plus<int>() );
return ret;
}
friend istream& operator>>( istream& is, CVector& v ) {
int nn {}; is >> nn;
if ( v.n != nn ) {
v.n = nn; delete[] v.data;
v.data = new int [v.n] {};
}
for ( size_t i = 0; i < static_cast<size_t>(v.n); ++i )
is >> v.data[i];
sum += accumulate( v.data, v.data + v.n, 0 );
return is;
}
friend class CMatrix;
};
int CVector::sum = 0;
class CMatrix {
CVector* data;
int n;
public:
CMatrix( int nn, CVector* dat )
: data { nullptr }, n { nn } {
data = dat;
}
CMatrix() : data { nullptr }, n { 0 } {}
~CMatrix() { delete[] data; }
CVector multi( const CVector& v1 ) const {
CVector ret { v1 };
for ( size_t i = 0; i < static_cast<size_t>(n); ++i ) {
ret.data[i] = 0;
for ( size_t ii = 0; ii < static_cast<size_t>(data[i].n); ++ii )
ret.data[i] += data[i].data[ii] * v1.data[ii];
}
return ret;
}
bool can_mul( const CVector& v1 ) const {
return n == v1.n;
}
};
int main()
{
size_t t {}; cin >> t;
while ( t-- ) {
int n {}; cin >> n;
auto vec_list = new CVector[n] {};
for ( int i = 0; i < n; ++i ) {
auto input = new int[n] {};
for ( int ii = 0; ii < n; ++ii )
cin >> input[ii];
vec_list[i] = CVector( n, input );
delete[] input;
}
CMatrix mat { n, vec_list };
vec_list = nullptr;
// vec_list 所有权已转移
int m {}; cin >> m;
auto input = new int[m] {};
for ( int i = 0; i < m; ++i )
cin >> input[i];
CVector vec { m, input };
delete[] input;
if ( mat.can_mul( vec ) )
cout << mat.multi( vec ) << endl;
else cout << "error" << endl;
}
}