2023.3.8上机练习

1.打印n阶菱形

#include<iostream>
using namespace std;
int main()
{
	int n;
	cin >> n;
	for (int i = 1; i < 2 * n + 1; i = i + 2)
	{
		int m = (2 * n + 1 - i) / 2;
		for (int k = 1; k < m; k++)
			cout << " ";
		for (int j = 0; j < i; j++)
			cout << "*";
		cout << endl;
	}
	for (int i = 2 * (n - 1) - 1; i > 0; i = i - 2)
	{
		int m = (2 * n + 1 - i) / 2;
		for (int k = 1; k < m; k++)
			cout << " ";
		for (int j = 0; j < i; j++)
			cout << "*";
		cout << endl;
	}
}

在这里插入图片描述

2.大整数加减法(使用字符串存储大整数再转化为整形)

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;

class BigInt
{
public:
	BigInt(string str) : strDigit(str) { }
private:
	string strDigit;//使用字符串存储大整数
	//都是全局函数声明为友元
	friend ostream& operator<<(ostream& out, const BigInt& src);
	friend BigInt operator+(const BigInt& lhs, const BigInt& rhs);
	friend BigInt operator-(const BigInt& lhs, const BigInt& rhs);

};
//打印函数
ostream& operator<<(ostream& out, const BigInt& src)
{
	out << src.strDigit;
	return out;
}

//大数加法
BigInt operator+(const BigInt& lhs, const BigInt& rhs) {
	//从后往前遍历字符串lhs,和rhs,用flag来标记是否需要进位,结果存在result数组中(反向的)
	string result;
	bool flag = false;
	int i = lhs.strDigit.length() - 1;//string的length和size没有区别,length是沿用C语言习惯,早先只有length
	int j = rhs.strDigit.length() - 1;

	for (; i >= 0 && j >= 0; --i, --j) //i 和 j其中一个会被减到负数然后退出for循环
	{
		int ret = lhs.strDigit[i] - '0' + rhs.strDigit[j] - '0';//单个位加减时需要减'0'转成整型,每次都重新定义一个新的ret
		if (flag)
		{
			ret += 1;//flag为true说明此位因为上一位进位而需要多加一个1
			flag = false;//再将其重新置为false
		}
		//两个if不能互换,否则不是下一位进1
		if (ret >= 10)
		{
			ret %= 10;
			flag = true;
		}
		result.push_back(ret + '0');
	}
	//如果遍历完,i还有剩下,第一个字符串没完
	if (i >= 0)//注意要取等,因为更短的那个字符串的下标是被减到-1,而不是0,0依然说明还剩余1位
	{
		while (i >= 0)
		{
			int ret = lhs.strDigit[i] - '0';
			if (flag)                 //前面加过来可能还有进位,然后当前可能为9,加了1之后又 = 10,又得进位,所以直接复制前面的代码
			{
				ret += 1;
				flag = false;
			}
			if (ret >= 10)
			{
				ret %= 10;
				flag = true;
			}
			result.push_back(ret + '0');
			i--;
		}
	}
	//第二个字符串没完
	else if (j >= 0)
	{
		while (j >= 0)
		{
			int ret = lhs.strDigit[j] - '0';
			if (flag)                 //前面加过来可能还有进位,然后当前可能为9,加了1之后又 = 10,又得进位,所以直接复制前面的代码
			{
				ret += 1;
				flag = false;
			}
			if (ret >= 10)
			{
				ret %= 10;
				flag = true;
			}
			result.push_back(ret + '0');
			j--;

		}
	}
	//最高位可能也进位
	if (flag) {
		result.push_back('1');
	}

	reverse(result.begin(), result.end());

	return result;//result是string类,而不是BigInt,因为隐式转换,p263
	//因为编译器看到该类的构造函数只接受一个实参(而且是string类的),所以可以触发隐式转换机制,定义string result时编译器也会构建一个BigInt类的临时对象,并把result赋值给他
	//函数里的return本来就是返回临时对象,这个时候就返回的就是那个BigInt类的临时对象
	//当然,参考书上的例子,即使后面函数用string类的result,编译器实际传入的也是BigInt的临时对象
	//如某成员函数定义为func(BigInt& a){...}; 调用时传入string类 func(result);也是合法的
}

//大数减法
BigInt operator-(const BigInt& lhs, const BigInt& rhs) {
	//让大的减小的,如果lhs比rhs小,则让rhs - lhs,然后最后添加负号
	string result;
	bool flag = false;
	bool minor = false;//标记lhs是否和rhs互换了

	string maxStr = lhs.strDigit;
	string minStr = rhs.strDigit;
	if (maxStr.length() < minStr.length())
	{
		//互换,让maxStr一直是最长的
		maxStr = rhs.strDigit;
		minStr = lhs.strDigit;
		minor = true;
	}
	//长度一样也得比较
	else if (maxStr.length() == minStr.length())
	{
		if (maxStr < minStr)
		{
			maxStr = rhs.strDigit;//让maxStr是最大的
			minStr = lhs.strDigit;
			minor = true;
		}
		else if (maxStr == minStr)
		{
			return string("0");
		}
	}

	int i = maxStr.length() - 1;//i肯定大于等于j,所以后面j会先完
	int j = minStr.length() - 1;

	for (; i >= 0 && j >= 0; --i, --j) {
		int ret = maxStr[i] - minStr[j];//减法的话,char类型相减就是int型了,不用+‘0’再相减
		/*if (ret >= 0)
		{
			result.push_back(ret + '0');
		} 一定要先看标记,因为被借位的话,当前ret需要减1*/
		if (flag)
		{
			ret -= 1;
			flag = false;
		}
		//当前位有可能因为被借位了而减,小于0,所以紧接着判断是否为负
		if (ret < 0)
		{
			ret += 10;// 如2 - 6,应该是12 - 6,所以为 2 - 6 + 10 = 6
			flag = true;
		}
		result.push_back(ret + '0');
	}

	//肯定是j先完,所以不用再像加法那样判断,而是直接把i多余的处理完
	while (i >= 0) {
		int ret = maxStr[i] - '0';
		if (flag) {
			ret -= 1;
			flag = false;
		}
		//同样的,ret可能原本是0,被借位了又为-1了
		if (ret < 0) {
			ret += 10;
			flag = true;
		}
		result.push_back(ret + '0');
		i--;
	}
	//翻转前先看看末尾有没有0,如1000,否则反转后就是0001
	while (result.back() == '0')
	{
		result.pop_back();
	}


	if (minor) {
		result.push_back('-');
	}
	reverse(result.begin(), result.end());
	return result;
}

int main()
{
	string s1;
	string A;
	string s2;
	getline(cin, s1);
	getline(cin, A);//把加减号定义为char会报错,getline第二个参数只能是string类型
	getline(cin, s2);
	BigInt int1(s1);
	BigInt int2(s2);
	if (A == "+") {
		cout << int1 + int2 << endl;
	}
	if (A == "-") {
		cout << int1 - int2 << endl;
	}
	return 0;
}

在这里插入图片描述
在这里插入图片描述

大神答案!!!!!!!!太牛了!!!!!!!!太强了!!!!!!!怎么有人脑子这么好使阿!!!!!!!!
本菜鸡勉勉强强看懂,复习复习!!!!!!!!!!

3.202104-1原题网址
在这里插入图片描述

#include<iostream>
using namespace std;
int arr[500][500];
int h[256]={0};
int main()
{
	int n, m, L;
	
	cin >> n >> m >> L;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < m; j++)
		{
			cin >> arr[i][j];
		}
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < m; j++)
		{
			for (int p = 0; p < L; p++)
			{
				if (arr[i][j] == p)
					h[p]++;
			}
		}
	}
	for (int i = 0; i < L; i++)
		cout << h[i] << " ";
	return 0;
}

4.202203-2原题网址
在这里插入图片描述

差分思想真的有点神奇欸

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 200010;

int res[N];

int main()
{
    int n, m, k;
    cin >> n >> m >> k;

    for (int i = 0; i < n; i++)
    {
        int t, c;
        cin >> t >> c;

        //在【l, r】时间段内做核酸,则t时刻可进入
        int l = max(t - k - c + 1, 0);
        l = min(l, 200000);
        int r = max(0, t - k);
        r = min(r, 200000);

        //在【l, r】时间段内能出行的计划个数加一
        res[l] += 1;
        res[r + 1] -= 1;
    }

    //利用差分计算每个时间的能出行个数
    for (int i = 1; i < 200001; i++)
    {
        res[i] += res[i - 1];
    }

    for (int i = 0; i < m; i++)
    {
        int q;
        cin >> q;
        cout << res[q] << endl;
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值