第一, 二题
P1601 A+B Problem(高精)
C++代码
#include <iostream>
#include <vector>
using namespace std;
vector <int> add(vector<int> &A, vector<int> &B)
{
if(A.size() < B.size()) return add(B, A);
vector<int> C;
int t = 0;
for(int i = 0; i < A.size(); i ++ )
{
t += A[i];
if(i < B.size()) t += B[i];
C.push_back(t % 10);
t /= 10;
}
if(t) C.push_back(t);
return C;
}
int main()
{
string a, b;
vector<int> A, B;
cin >> a >> b;
for(int i = a.size() - 1; i >= 0; i --) A.push_back(a[i] - '0');
for(int i = b.size() - 1; i >= 0; i --) B.push_back(b[i] - '0');
auto C = add(A, B) ;
for(int i = C.size() - 1; i >= 0; i --) cout << C[i];
cout << endl;
return 0;
}
P2142 高精度减法
#include <iostream>
#include <vector>
using namespace std;
bool cmp(vector<int> &A, vector<int> &B)
{
if (A.size() != B.size()) return A.size() > B.size();
for (int i = A.size() - 1; i >= 0; i -- )
if (A[i] != B[i])
return A[i] > B[i];
return true;
}
vector<int> sub(vector<int> &A, vector<int> &B)
{
vector<int> C;
for (int i = 0, t = 0; i < A.size(); i ++ )
{
t = A[i] - t;
if (i < B.size()) t -= B[i];
C.push_back((t + 10) % 10);
if (t < 0) t = 1;
else t = 0;
}
while (C.size() > 1 && C.back() == 0) C.pop_back();
return C;
}
int main()
{
string a, b;
vector<int> A, B;
cin >> a >> b;
for (int i = a.size() - 1; i >= 0; i -- ) A.push_back(a[i] - '0');
for (int i = b.size() - 1; i >= 0; i -- ) B.push_back(b[i] - '0');
vector<int> C;
if (cmp(A, B)) C = sub(A, B);
else C = sub(B, A), cout << '-';
for (int i = C.size() - 1; i >= 0; i -- ) cout << C[i];
cout << endl;
return 0;
}
高精度基础解题思路
①大整数存储
先用string类型存储我们所需要进行计算的大整数
再依次将每一位存入数组当中,需要注意的是,在数组中从小到大依次从大整数的低位开始进行存储
②将大整数所对应的数组拿来进行相应的加减乘除运算
(依据竖式加减乘除法则)
③将所得的结果存储进另一个空数组,并对每一位是否需要进位的查询操作
④将进位之后的结果数组依次高位向地位输出。
第三,四题
P1303 A*B Problem
题目描述
求两数的积。
输入格式
两行,两个整数。
输出格式
一行一个整数表示乘积。
输入样例
1
2
输出样例
2
C++代码
#include <iostream>
using namespace std;
const int N = 10000010;
int A[N], B[N], C[N];
int main()
{
string a, b;
cin >> a >> b;
int x = a.length(), y = b.length();
for(int i = x; i > 0; i --) A[i] = (a[x - i] - '0');
for(int i = y; i > 0; i --) B[i] = (b[y - i] - '0');
for(int i = 1; i <= x; i ++)
{
for(int j = 1; j <= y; j ++)
{
C[i + j - 1] += A[i] * B[j];
}
}
int l = x + y;
int t = 0;
for(int i = 1; i <= l; i ++)
{
C[i] += t;
t = C[i] / 10;
C[i] %= 10;
}
int k;
while(C[l] == 0 && l > 1) l --;
for(int i = l; l > 0; l --) cout << C[l];
return 0;
}
乘法题目需要注意的是每几位相乘的结果所在的位,比如个位乘百位和十位乘十位的结果均放置在答案数组的百位位置。
P1604 B进制星球
题目背景
进制题目,而且还是个计算器~~
题目描述
话说有一天,小Z乘坐宇宙飞船,飞到一个美丽的星球。因为历史的原因,科技在这个美丽的星球上并不很发达,星球上人们普遍采用B(2<=B<=36)进制计数。星球上的人们用美味的食物招待了小Z,作为回报,小Z希望送一个能够完成B进制加法的计算器给他们。 现在小Z希望你可以帮助他,编写实现B进制加法的程序。
输入格式
共3行第1行:一个十进制的整数,表示进制B。第2-3行:每行一个B进制数正整数。数字的每一位属于{0,1,2,3,4,5,6,7,8,9,A,B……},每个数字长度<=2000位。
输出格式
一个B进制数,表示输入的两个数的和。
输入样例
4
123
321
输出样例
1110
C++代码
#include <iostream>
using namespace std;
const int N = 10000100;
int A[N], B[N], C[N];
int main()
{
int n;
string a, b;
cin >> n >> a >> b;
int x = a.length(), y = b.length();
for(int i = x; i > 0; i --)
{
if(n >= 10 && a[x - i] >= 'A') A[i] = (a[x - i] - 'A' + 10);
else A[i] = (a[x - i] - '0');
}
for(int i = y; i > 0; i --)
{
if(n >= 10 && b[y - i] >= 'A') B[i] = (b[y - i] - 'A' + 10);
else B[i] = (b[y - i] - '0');
}
for(int i = 1 ; i <= x || i <= y; i ++)//相加
{
C[i] = A[i] + B[i];
}
//进位
int l = x + y;
int t = 0;
for(int i = 1; i <= l; i ++)
{
C[i] += t;
t = C[i] / n;
C[i] %= n;
}
while(C[l] == 0 && l > 0) l --;
for(int i = l; i > 0; i --)
{
if(C[i] < 10) cout << C[i];
else
{
cout << char('A' + C[i] - 10);
}
}
return 0;
}
本题和普通的高精度题目相比有两点需要注意的
①当输入进制数的时候,需要对进制数进行判断,是否为十进制以上的进制,并且输入的字母要转换成相对应的数字
②在最后进位的时候,进位的数值要以输入的B进制为准,并且结果输出时也需要进行字母的转换。
第五题
P2249 【深基13.例1】查找
题目描述
输入 n个不超过10的九次方的单调不减的(就是后面的数字不小于前面的数字)非负整数a1, a2,……an,然后进行m次询问,对于每次询问,给出一个整数 q,要求输出这个数字在序列中的编号,如果没有找到的话输出 -1 。
输入格式
第一行 2 个整数 n 和 m,表示数字个数和询问次数。
第二行 n 个整数,表示这些待查询的数字。
第三行 m 个整数,表示询问这些数字的编号,从 1 开始编号。
输出格式
m 个整数表示答案。
输入样例
11 3
1 3 3 3 5 7 9 11 13 15 15
1 3 6
输出样例
1 2 -1
C++'代码
#include <iostream>
using namespace std;
const int N = 1000010;
int n, m, p;
int q[N];
int main()
{
cin >> n >> m;
for(int i = 1; i <= n; i ++) cin >> q[i];
while(m --)
{
int l = 1, r = n;
cin >> p;
while(l + 1 < r)
{
int mid = (l + r) / 2;
if(q[mid] < p) l = mid + 1;
else r = mid;
}
if(q[l] == p) cout << l;
else if(q[r] == p) cout << r;
else cout << "-1";
cout << ' ';
}
return 0;
}
本题是一个最基本的二分
二分的基本概念就是把有序列答案区间进行中点的分割,根据某项性质求出答案存在的那一边,经过多次二分最终将答案所属区间确定为一个点。
二分较难的地方在于对于某些情况,mid = (l + r + 1)/ 2;
这里推荐一种比较好的办法,将二分的条件最后转化成while(l + 1 < r)这样可以有效的避免死循环
但是需要注意的是
在下面输出结果的时候 必须要对l和r分别都进行答案检验。
第六题
P1824 进击的奶牛
Farmer John建造了一个有N(2<=N<=100,000)个隔间的牛棚,这些隔间分布在一条直线上,坐标是x1,…,xN (0<=xi<=1,000,000,000)。
他的C(2<=C<=N)头牛不满于隔间的位置分布,它们为牛棚里其他的牛的存在而愤怒。为了防止牛之间的互相打斗,Farmer John想把这些牛安置在指定的隔间,所有牛中相邻两头的最近距离越大越好。那么,这个最大的最近距离是多少呢?
输入格式
第1行:两个用空格隔开的数字N和C。
第2~N+1行:每行一个整数,表示每个隔间的坐标。
输出格式
输出只有一行,即相邻两头牛最大的最近距离。
输入样例
5 3
1
2
8
4
9
输出样例
3
C++代码
#include<iostream>
#include<algorithm>
using namespace std;
int A[1000010];
int a, n, c;
bool check(int m)
{
int num = 0;
int x = A[1];//第一只牛的储存位置
for(int i = 2; i <= n; i ++)
{
if(A[i] - x < m) num ++;
else x = A[i];//变成“第一只牛”
if(num > a) return false;
}
return true;
}
int main()
{
cin >> n >> c;
for(int i = 1; i <= n; i ++ ) cin >> A[i];
sort(A + 1, A + n + 1);
a = n - c;
int l = 1, r = A[n] - A[1], mid;
while(l + 1 < r)
{
mid = (l + r) / 2;
if(check(mid)) l = mid;
else r = mid;
}
if(check(r)) cout << r;
else cout << l;
return 0;
}
这个题目主要是对于题目的理解,主要更是对于check函数的理解,check函数的作用是检验mid这个答案是否合理。