蓝桥杯练习-3.12

蓝桥杯练习-3.12

代码练习

• 高精度加法

资源限制

时间限制:1.0s 内存限制:512.0MB

问题描述

输入两个整数ab,输出这两个整数的和。ab都不超过100位。

算法描述

由于ab都比较大,所以不能直接使用语言中的标准数据类型来存储。对于这种问题,一般使用数组来处理。
  定义一个数组AA[0]用于存储a的个位,A[1]用于存储a的十位,依此类推。同样可以用一个数组B来存储b
  计算c = a + b的时候,首先将A[0]与B[0]相加,如果有进位产生,则把进位(即和的十位数)存入r,把和的个位数存入C[0],即C[0]等于(A[0]+B[0])%10。然后计算A[1]与B[1]相加,这时还应将低位进上来的值r也加起来,即C[1]应该是A[1]、B[1]和r三个数的和.如果又有进位产生,则仍可将新的进位存入到r中,和的个位存到C[1]中。依此类推,即可求出C的所有位。
  最后将C输出即可。

输入格式

输入包括两行,第一行为一个非负整数a,第二行为一个非负整数b。两个整数都不超过100位,两数的最高位都不是0。

输出格式

输出一行,表示a + b的值。

样例输入

20100122201001221234567890
2010012220100122

样例输出

20100122203011233454668012

代码实现

#include <stdio.h>
#include<string.h>
int main()
{
    int i,alen,blen,n;
	char a[101], b[101], c[103];//对应存两个加数和 和的字符数组,因为数字太大了,只能换为字符存储
	memset(c,0,sizeof(c));//清零
    scanf("%s%s", a, b);
     alen = strlen(a);
     blen = strlen(b);
    if (alen >= blen)//得到较大的那个长度,当作循环条件
    {
        n = alen;
    }
    else n = blen;
    for (i = 0; i < n; i++)
    {
        if (i < alen)
            c[i] += a[alen-i-1] - '0';//因为是字符,所以需要减去字符0,得到的ASCII码就是对应的数,而且是从低位开始加起,所以数组从倒着的开始
        if (i < blen)
            c[i] += b[blen-i-1] - '0';
        if (c[i] >= 10)
        {
            c[i+1] = c[i] / 10;//如果加起来大于10,要向高位进位
            c[i] %= 10;//然后本位得到余下的
        }
    }
    if (c[n] != 0)
    {
        for (i = n; i >= 0; i--)//倒着输出便是和
        printf("%d", c[i]);
    }
    else
    {
        for (i = n - 1; i >= 0; i--)//倒着输出便是和
        printf("%d", c[i]);
    }
    return 0;
}

❕注意:C++中,全局阈只能声明、初始化变量; 不能用于赋值、运算、调用函数等!!!也要注意,当两数都是相同位数时,最后输出的时候就不是n位了,而是n+1位

• 阶乘运算

资源限制

时间限制:1.0s 内存限制:512.0MB

问题描述

输入一个正整数n,输出n!的值。
  其中n!=1 *2 * 3… * n。

算法描述

n!可能很大,而计算机能表示的整数范围有限,需要使用高精度计算的方法。使用一个数组A来表示一个大整数aA[0]表示a的个位,A[1]表示a的十位,依次类推。
  将a乘以一个整数k变为将数组A的每一个元素都乘以k,请注意处理相应的进位。
  首先将a设为1,然后乘2,乘3,当乘到n时,即得到了n!的值。

输入格式

输入包含一个正整数nn<=1000。

输出格式

输出n!的准确值。

思路

根据算法描述,我们构建一个足够大的数组来存放这个大数的每一位,然后,我们用一个for循环来循环我们要乘的数,因为数每一位(个位,十位,百位…)都要乘,所以要有第二个循环,来循环每一个数组元素,这里需要用到进位,我们在每一轮乘数的开始,把进位初始为0,数组当前开到的最大下标记为high = 0,我们每一组元素乘完i再加上低位的进位以后,只需%10保留个位填到当前数组下标即可,然后进位数/10,一直到数组最大下标,如果这个时候进位数还有,就说明要开数组了,因为总数的位数又增加了。

代码实现:

#include <iostream>
using namespace std;
const int N = 100000;
int a[N];
int n;
int main()
{
    cin >> n;
    a[0] = 1;
    int r;//r代表进位数
    int high = 0;//high表示现在数组开到第几位了,第一次为0
    for (int i = 2; i <= n; i++)//从2开始乘
    {
        r = 0;//每乘完一个数后,进位都初始化为0
        for (int j = 0; j <= high; j++)
        {
            int mul = a[j] * i + r;
            a[j] = mul % 10;//当前位数保留个位的
            r = mul / 10;//进位,这里不用担心进位是很大的数怎么办,因为我们只是先把数组填满,多出来的肯定位数已经大过了数组上界high,没有影响
        }
        while(r)//因为进位可能不是一个个位数,所以当当前可以开到的最大数组个数都被填满数字了以后,
                //进位仍然不为0,就继续开拓数组,把进位一个个往后面填上
        {
            a[++high] = r % 10;
            r /= 10;
        }
    }
    for (int i = high; i >= 0; i--)
    {
        cout << a[i];
    }
    return 0;
}

蓝桥杯练习-3.12

• G 螺旋折线(第九届蓝桥杯)

Description

如图p1.png所示的螺旋折线经过平面上所有整点恰好一次。

对于整点(X, Y),我们定义它到原点的距离dis(X, Y)是从原点到(X, Y)的螺旋折线段的长度。

例如dis(0, 1)=3, dis(-2, -1)=9

给出整点坐标(X, Y),你能计算出dis(X, Y)吗?

Input

X和Y

对于40%的数据,-1000 <= X, Y <= 1000

对于70%的数据,-100000 <= X, Y <= 100000

对于100%的数据, -1000000000 <= X, Y <= 1000000000

Output

输出dis(X, Y)

思路

**蓝桥杯练习-3.12
**

先分别找出y>0黄点的坐标变化规律,再找出y<0黄点的坐标变化规律。

当x的绝对值大于y的绝对值时也就是dis点在竖着的折现上时,都要用x轴上方黄色的点来计算。

当x的绝对值小于y的绝对值时也就是dis点在横着的折现上时,用x轴下方黄色的点来计算。

当y等于0也就是dis点在x轴上时单独计算。

代码实现(不完全对):

#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
long long dis(long long x, long long y)
{
    if(x == 0)
    {
        if (y > 0)  return pow((2 * y), 2) - y;
        else if (y < 0)  return pow((2 * y), 2) - y + 4 * y;
        else if (y == 0)  return 0;
    }
    else if (x > 0)
    {
        if (y == 0)
        {
            return pow((2 * x), 2) + x;
        }
        else if (y > 0)
        {
            if (y == x)  return pow((2 * x), 2);
            else if (y < x)  return pow((2 * x), 2) + x - y;
            else if (y > x)  return pow((2 * y), 2) - y + x;
        }
        else if (y < 0)
        {
            if (abs(y) == x)  return pow((2 * x), 2) + 2 * x;
            else if (abs(y) < x)  return pow((2 * x), 2) + 2 * x - (x + y);
            else if (abs(y) > x)  return pow((2 * y), 2) - y + 4 * y - x;
        }
    }
    else if (x < 0)
    {
        if (y == 0)
        {
            return pow((2 * x), 2) + 2 * x + x;
        }
        else if (y > 0)
        {
            if (y == abs(x))
            {
                return pow((2 * x), 2) + 2 * x;
            }
            if (y < abs(x))  return pow((2 * x), 2) + 2 * x + x + y;
            if (y > abs(x))  return pow((2 * y), 2) - y + x;
        }
        else if (y < 0)
        {
            if ((abs(x) - abs(y)) == 1)  return pow((2 * y), 2) + y - 4 * y - x;
            else if (abs(y) < abs(x))  return pow(2 * (x + 1), 2) - 5 * (x + 1) + 1 + y;
            else if (abs(y) >= abs(x))  return (4 * abs(y) + 3) * abs(y) + abs(x);
        }
    }
}
int main()
{
    long long x, y;
    scanf("%lld%lld",&x, &y);
    printf("%lld\n",dis(x, y));
    return 0;
}

❕注意:注意函数类型为long long,传入的参数类型也为long long

上一篇:递归和尾递归


下一篇:c语言自学打卡