当前位置: 首页 > news >正文

算法基础 1

目录

一、模拟

1.1 多项式输出

1.2 蛇形矩阵

介绍一种通用解法——解决矩阵填数问题

1.3 字符串展开

二、高精度

2.1 高精度加法

2.2 高精度减法

2.3 高精度乘法

2.4 高精度除法(高精度 / 低精度)


一、模拟

1.1 多项式输出

题目链接:P1067 [NOIP 2009 普及组] 多项式输出 - 洛谷 注意模拟+分类讨论即可

#include<iostream>
#include<cmath>
using namespace std;
​
int main()
{int n = 0;cin >> n;for(int i = n;i >= 0;i--){int m = 0;cin >> m;if(m == 0) continue;//1.处理符号if(m > 0 && i != n)cout << '+';else if(m < 0)cout << '-';
​//2.处理数字int a = abs(m);if(a != 1 || (a == 1 && i == 0)) cout << a;//3.处理次数if(i == 0)continue;else if(i == 1)cout << 'x';elsecout << "x^" << i;}
​return 0;
}
1.2 蛇形矩阵

题目链接:P5731 【深基5.习6】蛇形方阵 - 洛谷

介绍一种通用解法——解决矩阵填数问题

1.定义方向向量

int dx[] = {0,1,0,-1};
int dy[] = {1,0,-1,0}; 

右、下、左、上(顺时针)

注意:此处坐标轴,以下为x正方向,以右为y正方向。因为要和二维数组相适应

2.根据规则结合方向向量填数

  • 超一个方向走,一边走一边填数,直到越界

  • 越界之后,结合方向向量,重新计算出新的坐标以及方向

#include<iostream>
​
using namespace std;
​
const int N = 15;
//判断坐标(x,y)中是否已经填数
int arr[N][N];
​
//定义方向向量
int dx[] = {0,1,0,-1};
int dy[] = {1,0,-1,0};
​
​
int main()
{//处理输入int n = 0;cin >> n;
​//模拟填数过程int x = 1,y = 1;int pos = 0;//方向int cnt = 1;//填的数字while(cnt <= n*n){arr[x][y] = cnt;//计算下一个位置int a = x + dx[pos],b = y + dy[pos];//判断是否越界if(a < 1 || a > n || b < 1 || b > n || arr[a][b]){pos = (pos + 1) % 4;a = x + dx[pos],b = y + dy[pos];}//更新坐标x = a,y = b;cnt++;}//输出for(int i = 1;i <= n;i++){for(int j = 1;j <= n;j++){printf("%3d",arr[i][j]);}cout << endl;}
​return 0;
}
1.3 字符串展开

题目链接:P1098 [NOIP 2007 提高组] 字符串的展开 - 洛谷 纯模拟+考察基础代码能力

对于复杂的条件判断,建议封装函数,这样代码较为简洁,方便debug

C++ 标准库中有 (判断是否为数字)和 isalpha (判断是否为字母)这两个函数,它们是 C 标准库函数,在 <cctype> 头文件中定义(对应 C 语言中的 <ctype.h>

还有类似的函数:

  • isalnum:判断是否是字母或数字

  • isspace:判断是否是空白字符(如空格、换行、制表符等)

  • islower / isupper:判断是否是小写或大写字母

  • tolower / toupper:转换为小写或大写

此题我们会用到 isdigitislower

#include<iostream>
#include<algorithm> // 调用reverse函数
#include<cctype> // 调用isdigit和islower函数
using namespace std;
​
string s;
string ret;
int p1,p2,p3,n;
​
void add(char left,char right)
{string t;//遍历其中的字符for(char ch = left + 1;ch < right;ch++){char tmp = ch;//处理p1if(p1 == 2 && islower(tmp)) tmp -= 32; //注意只对字母字符改变大小写else if(p1 == 3) tmp = '*';//处理p2for(int i = 0;i < p2;i++){t += tmp;}}//处理p3 (要在循环外进行,否则逻辑错误)if(p3 == 2) reverse(t.begin(),t.end());ret += t;
}
​
int main()
{cin >> p1 >> p2 >> p3 >> s;n = s.size();for(int i = 0;i < n;i++){char ch = s[i];if(s[i] != '-' || i == 0 || i == n-1) ret += ch;else{char left = s[i-1],right = s[i+1];//判断是否展开if((isdigit(left) && isdigit(right) && right > left) ||(islower(left) && islower(right) && right > left)){add(left,right);}else{ret += ch;}}}cout << ret << endl;return 0;
}

二、高精度

当数据的值特别大,各种类型都存不下的时候,此时就要用高精度算法来计算加减乘除;

  • 先用字符串读入这个数,然后用数组逆序存储该数的每一位

  • 利用数组,模拟加减乘除运算的过程

高精度算法本质上还是模拟算法,用代码模拟小学列竖式计算加减乘除的过程

2.1 高精度加法

题目链接:P1601 A+B Problem(高精) - 洛谷

算法原理:

  • 模拟小学列竖式计算的过程

  • 先用字符串读入,拆分每一位,逆序放在数组中

  • 利用数组,模拟小学列竖式计算加法的过程(对应位相加,加上进位,处理进位,处理余数)

#include<iostream>
using namespace std;
​
const int N = 1e6 + 10;
int a[N],b[N],c[N];
int la,lb,lc; // 记录数字位数
​
//高精度加法的模板 ---  c = a + b;
void add(int a[],int b[],int c[])
{for(int i = 0;i < lc;i++){c[i] += a[i] + b[i]; // 对应位相加,再加上进位c[i+1] = c[i] / 10; // 处理进位c[i] %= 10; // 处理余数}if(c[lc]) lc++; // 处理边界情况,如果最后一位进位,则...
}
​
​
int main()
{string x,y;cin >> x >> y;//1.拆分每一位,逆序放在数组中la = x.size(); lb = y.size(); lc = max(la,lb);for(int i = 0;i < la;i++) a[la - 1 - i] = x[i] - '0';// 这里还是字符,得转换为数字进行加法for(int i = 0;i < lb;i++) b[lb - 1 - i] = y[i] - '0';//2.模拟加法过程add(a,b,c);//输出结果for(int i = lc - 1;i >= 0;i--) cout << c[i];cout << endl;return 0;
}
2.2 高精度减法

题目链接:P2142 高精度减法 - 洛谷

算法原理:

  • 先比较大小,然后用较大得数减去较小的数 —— 先比较长度,再按字典序比较

  • 先用字符串读入,然后拆分每一位,逆序放进数组中

  • 利用数组,模拟列竖式减法的过程

    • 先是对应位相减,然后处理借位

    • 如果减的结果小于0,往前借一位,然后这一位加上10

#include<iostream>
using namespace std;
​
const int N = 1e6 + 10;
​
int a[N],b[N],c[N]; // a - 被减数 b - 减数
int la,lb,lc;
​
//比大小
bool cmp(string& x,string& y)
{//先比较长度if(x.size() != y.size()) return x.size() < y.size();//再按照字典序的方式比较return x < y;
}
​
//高精度减法的模板 —— c = a - b
void sub(int a[],int b[],int c[])
{for(int i = 0;i < lc;i++){c[i] += a[i] - b[i]; // 对应位相减,然后处理借位,此处必须是+=,不能是=if(c[i] < 0){c[i] += 10;c[i+1] -= 1;//借位}}//处理前导0while(lc > 1 && c[lc-1] == 0) lc--;
}
​
int main()
{string x,y;cin >> x >> y;
​//比大小if(cmp(x,y)){swap(x,y);cout << '-';}//1.拆分每一位,逆序放在数组中la = x.size(); lb = y.size(); lc = max(la,lb);for(int i = 0;i < la;i++) a[la - 1 - i] = x[i] - '0';for(int i = 0;i < lb;i++) b[lb - 1 - i] = y[i] - '0';
​//2.模拟减法过程sub(a,b,c);//输出结果for(int i = lc - 1;i >= 0;i--) cout << c[i];cout << endl;return 0;
}
2.3 高精度乘法

题目链接:P1303 A*B Problem - 洛谷

算法原理 —— 模拟列竖式过程

  • 先用字符串读入,然后拆分每一位,逆序放在数组中

  • 利用数组,模拟列竖式乘法过程

    (采取无进位相乘,然后相加,最后处理进位)

            1  2  3 *4  5  6—————————6  12 185 10 154 8 12——————————————4 13 28 27 181  3  2  1    <—— 处理进位——————————————5  6  0  8  8
#include<iostream>
​
using namespace std;
​
const int N = 1e6 + 10;
int a[N],b[N],c[N];
int la,lb,lc;
​
//高精度乘法模板 —— c = a * b
void mul(int a[],int b[],int c[])
{//无进位相乘,再相加for(int i = 0;i < lc;i++){for(int j = 0;j < lb;j++){c[i + j] += a[i] * b[j];}}//处理进位for(int i = 0;i < lc;i++){c[i+1] += c[i] / 10;c[i] %= 10;}//处理前导0while(lc > 1 && c[lc-1] == 0) lc--;
}
​
​
int main()
{string x,y; cin >> x >> y;la = x.size();lb = y.size();lc = la + lb;//1.拆分每一位,逆序放在数组中for(int i = 0;i < la;i++) a[la - 1 - i] = x[i] - '0';for(int i = 0;i < lb;i++) b[lb - 1 - i] = y[i] - '0';//2.模拟无进位乘法过程mul(a,b,c);for(int i = lc - 1;i >= 0;i--) cout << c[i];cout << endl;return 0;
}
2.4 高精度除法(高精度 / 低精度)

题目链接:P1480 A/B Problem - 洛谷

算法原理:

  • 存数不赘述

  • 模拟小学列竖式计算两数相除过程

    • 定义一个指针 i 从高位遍历被除数,一个变量 t 标记当前被除的数,记除数是 b ;

    • 更新一个当前被除的数 t = t * 10 + a[i];

    • t / b 表示这一位的商,t % b 表示这一位的余数

    • 用 t 记录这一次的余数,遍历到下一位的时候重复上面的过程

  • 注意前导 0

#include<iostream>
using namespace std;
​
typedef long long LL;
​
const int N = 1e6 + 10;
int a[N],b,c[N];
int la,lc;
​
//高精度除法的模板 ——  c = a / b; 高精度 / 低精度
void sub(int a[],int b,int c[])
{LL t = 0;//标记每次除完之后的余数for(int i = la - 1;i >= 0;i--){//计算当前的被除数t = t * 10 + a[i];c[i] = t / b;t %= b;}//处理前导0while(lc > 1 && c[lc-1] == 0) lc--;
}
​
int main()
{string x; cin >> x;cin >> b;la = x.size();lc = la;for(int i = 0;i < la;i++) a[la - 1 - i] = x[i] - '0';sub(a,b,c);//模拟除法的过程for(int i = lc - 1;i >= 0;i--) cout << c[i];cout << endl;return 0;
}
http://www.lryc.cn/news/618016.html

相关文章:

  • 为什么TEXT不区分大小写,而BLOB严格区分?
  • redis笔记(二)
  • OpenBMC中phosphor-dbus-interfaces深度解析:架构、原理与应用实践
  • 02Vue3
  • 贪心----3. 跳跃游戏 II
  • 使用MAS(Microsoft Activation Scripts)永久获得win10专业版和office全套
  • 进程线程切换的区别
  • 【MATLAB 2025a】安装离线帮助文档
  • 第16届蓝桥杯Python青少组中/高级组选拔赛(STEMA)2025年3月9日真题
  • 【k近邻】Kd树的构造与最近邻搜索算法
  • mhal_gpio.c记录gpio相关寄存器和gpio操作函数
  • 【优化】图片批量合并为word
  • 部署open-webui到本地
  • Linux中配置DNS
  • 牛客疑难题(5
  • 基于Springboot+UniApp+Ai实现模拟面试小工具九:移动端框架搭建
  • 【GPT入门】第45课 无梯子,linux/win下载huggingface模型方法
  • 应用程序已被Java安全阻止解决方法
  • 支持小语种的在线客服系统,自动翻译双方语言,适合对接跨境海外客户
  • CSS预处理器之Sass全面解析与实战指南
  • C#图形库SciChart与ScottPlot及LiveCharts2对比
  • 数据类型 string
  • 【lucene】livedocs描述
  • AR 智能眼镜:从入门到未来
  • MySQL 基本语法
  • 【listlist模拟】
  • Buildroot(二)
  • Python 类元编程(定制描述符的类装饰器)
  • 文旅元宇宙:科技重塑数字消费新文明
  • 【vue(一))路由】