高精度 二分 算法题目

第一, 二题

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这个答案是否合理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值