day05:枚举&模拟&高精度(了解原理,实现高精加)&文件重定向
枚举,其实就是穷举,把所有答案都遍历一遍,看是否满足要求
模拟:这个怎么说呢?其实就是让你干什么,你就干什么,按照它的要求来就是了。
对于枚举和模拟的题目主要是通过练题,提升自己的代码量来巩固,没有太多的知识点。
高精度
一个十分经典的问题:输入a b,求a+b的和
普通的话我们直接cout<<a+b就可以了,但是如果告诉你:
a,b是两个有100位长度的数据呢?这明显就不行了啊!
即使unsigned long long 的最大值也不过2^64=1.8e19
这就需要使用高精算法了,一般这类算法考的比较少,但是这样有趣的知识点,我们还是学习一下吧!
算法介绍
a = 11111111
b = 22222222
a+b = 33333333
a = 8888,8888
b = 9999,9999
a+b = 17 17 17 17, 17 17 17 17 (每位对应求和)
= 17 17 17 17, 17 17 18 7 (开始进位)
= 17 17 17 17, 17 18 8 7 (继续进位)
= 17 17 17 17, 18 8 8 7 (继续进位)
= 17 17 17 18, 8 8 8 7 (继续进位)
= 17 17 17 18, 8 8 8 7 (继续进位)
= 17 17 18 8, 8 8 8 7 (继续进位)
= 17 18 8 8, 8 8 8 7 (继续进位)
= 18 8 8 8, 8 8 8 7 (继续进位)
= 1, 8 8 8 8, 8 8 8 7 (进位结束)
这就是高精度加法的原理,但是我们发现每次进位都是从后向前,
于是可以直接将数据翻转过来处理,最后输出或返回时在逆序即可。
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
//注意开全局变量,如果是局部变量很容易出现问题
const int MAXN=10005;
int A[MAXN],B[MAXN],C[MAXN], Ans[MAXN],Len_A,Len_B,Len_Ans;
void Read(int A[],int &Len) {
string cur; cin>>cur;
Len=cur.length();
for(int i=0; i<Len; i++) A[i] = cur[i]-'0';
reverse(A,A+Len);//对A[0]..A[Len]进行翻转
}
int main() {
Read(A,Len_A); Read(B,Len_B);
Len_Ans=max(Len_A,Len_B);
for(int i=0; i<=Len_Ans; i++) {
Ans[i]=A[i]+B[i]+C[i]; //加上前一位的进位值
if(Ans[i]>9) C[i+1]=Ans[i]/10, Ans[i]-=10;//处理进位值
}
while(Ans[Len_Ans]>0) Len_Ans++; //位数是否增加
for(int i=Len_Ans-1; i>=0; i--) cout<<Ans[i];//输出结果
return 0;
}//该高精加模板源自CCF教材
高精加减乘的实现原理是大同小异的,高精除法需要转化使用减法的方式比较麻烦,但是很少考到这个,建议就是如果有时间可以将高精加减乘按照自己的风格写一遍。
另外注意一点:部分同学喜欢将计算结果返回为string类型,当然笔者也喜欢这样!
可是在string使用是会用到str.append()的用法,而这样的用法是在C11版本才有的,如果不支持C11那么这样的写法是不能AC的,比如:提交奥赛一本通的网站就会出bug
文件重定向
这个其实主要对于数据测试和竞赛中有用,平常用不上,但是比赛又必须要使用
freopen("输入文件名", "r", stdin); //替代我们的手动输入,将文件中内容读入输入流中
freopen("输出文件名", "w", stdout);//将输出流中的数据写入文件中
其实用这个来代替我们的手动输入是比较方便的,大家可以多习惯这样的用法。
举例:
普及组
(请选手务必仔细阅读本页内容)
一、题目概况
中文题目名称 | a+b |
---|---|
英文题目与子目录名 | ab |
提交源程序文件名 | ab.cpp |
可执行文件名 | ab.exe |
输入文件名 | ab.in |
输出文件名 | ab.out |
每个测试点时限 | 1秒 |
测试点数目 | 10 |
每个测试点分 | 10 |
附加样例文件 | 有 |
结果比较方式 | 全文比较(过滤行末空格及文末回车) |
题目类型 | 传统 |
运行内存上限 | 256MB |
编译命令 | g++ -o test test.cpp -lm |
测试时长 | 10分钟 |
二、注意事项:
1、文件名(程序名和输入输出文件名)必须使用英文小写。
2、C/C++中函数 main()的返回值类型必须是 int,程序正常结束时的返回值必须是0。
3、全国统一评测时采用的机器配置为:CPU AMD Athlon(tm) Ⅱx2 240 process 2.8GHZ, 内存 4G,上述时限以此配置为准。
4、只提供 Linux 格式附加样例文件。
5、提交的程序代码文件的放置位置请参照各省的具体要求。
6、特别提醒:评测在当前最新公布的 NOI Linux 下进行,各语言的编译器版本以其为准。
【题目描述】输入a,b, 输出a+b的结果(0<=a+b<=2^31)。
#include<iostream>
using namespace std;
int main() {
freopen("ab.in", "r", stdin);
freopen("ab.out", "w", stdout);
int a,b; cin>>a>>b;
cout<<a+b;
return 0;
}
这样程序就会从文件 ab.in
里面读取前两个数据,分别赋值给a,b,从而替代我们手动输入的过程。并且会将a+b的结果保存到文件 ab.out
里面,就不会在控制台窗口输出(也就是小黑方框)。
另外注意一点:题目一般会告诉你,我要提交什么样的源文件,比如 ab.cpp