[蓝桥杯练题]十四届A组原题

已经不是小时候了,不能因为自己的小情绪就不干这不干那,不能因为不想而逃避,要自己为自己的未来打算,如果最后被社会淘汰了,就不能养活自己了。

平方差高精度

A、B可达 正负10^100,用任何数据类型都接不下它,可数据类型可看下。

c/c++中int,long,long long的取值范围_c++ long long 取值范围-CSDN博客

所以很明显,这题要用大数的方法。

存储大数

先用字符串录入,再进行转换

运算大数

主要是进位问题和最高位的位数问题。

出错总结

1. 在把字符转换成数字时,没有 - '0'

[蓝桥杯练题]十四届A组原题_第1张图片

2. 读入数字时,是高位在前,所以在字符串里,先读入的是高位,高位数字存储在低位。

3. 两数相乘,用两层for循环,逐个相乘,至于是后结果的最高位数,是两个数长度之和。

4. 函数名后没有带[下标],也不会报错,呜呜。

[蓝桥杯练题]十四届A组原题_第2张图片

5. 我将平方后的数组容量从150 升高到了300,多通过了两个。

代码:

#include 
#include
#include
#include
using namespace std;

  int num1[150];   //个位在下标为1的地方
  int num2[150];
  //int flag1 = 0;  //是否为负数
  //int flag2 = 0;
  int numlen1;
  int numlen2;
  int squ_num1[150];  //平方后的数字
  int squ_num2[150]; 
  int sub[150];  //平方减之后的数字
  int squ_numlen1;
  int squ_numlen2;
  int sub_num;

void shift(string s1,string s2,int len1,int len2)
{
  //判断符号,并将数字数组的第一位 1 代表正 -1代表负
  if(s1[0] == '-')  //如果是负号 
  {
    //flag1 = 1;
    num1[0] = -1;
    numlen1 = len1;
    for(int i = len1 - 1 ; i >= 0; i--)//把数字粘过去
    {
      num1[len1-i] = s1[i]-'0';
    }
  }else{
    num1[0] = 1;
    numlen1 = len1+1;
    for(int i = len1 - 1 ; i >= 0 ; i--)//把数字粘过去
    {
      num1[len1-i] = s1[i] - '0';
    }
  }

  if(s2[0] == '-')  //如果是负号 
  {
    //flag2 = 1;
    num2[0] = -1;
    numlen2 = len2;
    for(int i = len2 - 1 ; i >= 0 ; i--)//把数字粘过去
    {
      num2[len2-i] = s2[i]-'0';
    }
  }else{
    num2[0] = 1;
    numlen2 = len2+1;
    for(int i = len2 - 1 ; i >= 0; i--)//把数字粘过去
    {
      num2[len2-i] = s2[i]-'0';
    }
  }
  return ;
}

//大数的平方
int square(int numlen,int num[150],int (&squ_num)[150])
{
  /*int cin = 0;
  squ_num[0] = 1;  //平方后为正数,0也算吧
  int squ_numlen = numlen;
  for(int i = 1 ; i < numlen ; i++)
  {
    int x = num[i]*num[i];
    squ_num[i] = (x+cin)%10;
    cin = (x+cin)/10;  //保证每个cin 都是该次的cin
  }
  if(cin != 0)
  {
    squ_num[numlen] = cin;
    squ_numlen++;
  }*/
  int cin  = 0;
  squ_num[0] = 1;
  int squ_numlen = 2*numlen-2;
  for(int i = 1 ; i < numlen; i++)
  {
    for(int j = 1 ; j < numlen ; j++)
    {
      int x = num[i] * num[j] + cin;
      squ_num[j+i-1] = x % 10;
      cin = x / 10;  //两个一位数相乘,最多两位
    }
  }
  if(cin != 0)
  {
    squ_num[2*numlen-2] = cin;
    squ_numlen = 2*numlen-1;
  }

  return squ_numlen;
}
//大数相减
void subtract(int squ_num11[150],int squ_num21[150])
{
  int cin = 0 ;
  sub[0] = 1;  //设为正数
  int end = min(squ_numlen1,squ_numlen2);
  int fend = max(squ_numlen1,squ_numlen2);
  for(int i = 1 ; i < end ;i++)
  {
    if((squ_num11[i] - cin) >= squ_num21[i])
    {
      sub[i] = squ_num11[i] - squ_num21[i] -cin;
      cin = 0;
    }else if((squ_num11[i] - cin) < squ_num21[i]) {
      sub[i] = squ_num11[i]+10-squ_num21[i]-cin;
      cin = 1;
    }
  }
  /*if(cin == 1)
  {
    sub[end] = squ_num11[end]-1;
  }*/
  for(int i = end ; i < fend ; i++)
  {
    if(squ_num11[i] - cin < 0)
    {
      sub[i] = squ_num11[i] + 10 - cin;
      cin = 1;
    }else if(squ_num11[i] - cin >= 0)
    {
      sub[i] = squ_num11[i] - cin;
      cin = 0;
    }

  }
  sub_num = fend-1;
  return ;
}

//大数比较大小  1更大返回1 2更大返回0
int cmp()
{
  if(squ_numlen1 > squ_numlen2)
  {
    return 1;
  }else if(squ_numlen1 < squ_numlen2){
    return 0;
  }else {
    for(int i = squ_numlen1 ; i > 0 ; i--)
    {
      if(squ_num1[i] > squ_num2[i])
      {
        return 1;
        break;
      }else if(squ_num1[i] < squ_num2[i]){
        return 0;
        break;
      }
    }
  }
  return -1;
}



int main()
{
  // 请在此输入您的代码
  //1.存储大数:以字符串的方式输入,再将每个字符转成数字放入数组。
  string s1;
  string s2;

  cin >> s1;
  cin >> s2;

  //将字符转成数字放入数组,注意判断正负数

  int len1 = s1.length();
  int len2 = s2.length();

  shift(s1,s2,len1,len2);

  //进行加法和减法
  //一共四种情况(AB是绝对值),-A`+B` A`-B` A`+B` -A`-B`
  //(A + B)*(A - B ) (包括负号)

  //或者直接 A^2  ,两数相乘最多两位,注意进位
  squ_numlen1 = square(numlen1,num1,squ_num1);
  squ_numlen2 = square(numlen2,num2,squ_num2);

  if(cmp() == 1)
  {
    subtract(squ_num1,squ_num2);
    sub[0] = 1;
  }else if(cmp() == 0)
  {
    subtract(squ_num2,squ_num1);
    sub[0] = -1;
  }else 
  {
    sub[1]=0;
    sub[0] = 1;
    sub_num = 1;
  }
  
  //把sub打印出来
  if(sub[0] == -1)
  {
    cout << '-';
  }
  int flag = 1;  //用来标志这个0是否是无效0

    //
    cout << sub_num << endl;
    for(int j = 0 ; j < squ_numlen1 ; j++){cout << squ_num1[j] << ' ';}
    cout << endl;
    for(int j = 0 ; j < squ_numlen2 ; j++){cout << squ_num2[j] << ' ';}



  for(int i = sub_num ; i > 0 ; i--)
  {
    if(i!=1 && flag && sub[i] == 0){}
    else {
      flag = 0;
      cout << sub[i] ;
    }
  }


  


  return 0;
}

你可能感兴趣的:(蓝桥杯,算法)