实现
码前思考
- 第一想法就是使用高精度整数运算;
- 需要注意0是正号还是负号;
代码实现
//大整数的加法和减法!
//注意0的符号,这里0的符号是-
#include "bits/stdc++.h"
using namespace std;
const int maxn = 100;
int t;
char A[maxn];
char B[maxn];
char C[maxn];
struct bign{
int d[100];
int len;
//代表是整数还是负数
bool flag;
//一定要定义构造函数
bign(){
fill(d,d+maxn,0);
len = 0;
flag = true;
}
};
//转换函数
bign change(char str[]){
//自动调用构造函数的
bign num;
int len = strlen(str);
//首先判断正数还是负数
if(str[0] == '-'){
for(int i=1;i<len;i++){
num.d[len-i-1] = str[i] - '0';
}
num.len = len-1;
num.flag = false;
}else{
for(int i=0;i<len;i++){
num.d[len-i-1] = str[i] - '0';
}
num.len = len;
}
return num;
}
bign sum(bign a,bign b){
bign num;
//表示进位
int carry = 0;
//开始循环
for(int i=0;i<a.len||i<b.len;i++){
int res = a.d[i] + b.d[i] + carry;
num.d[i] = res%10;
carry = res/10;
num.len++;
}
//如果最后还有进位
while(carry!=0){
num.d[num.len] = carry%10;
carry = carry / 10;
num.len++;
}
return num;
}
bign sub(bign a,bign b){
bign num;
//使用减法
for(int i=0;i<a.len||i<b.len;i++){
if(a.d[i] < b.d[i]){
num.d[i] = a.d[i]+10-b.d[i];
a.d[i+1]--;
}else{
num.d[i] = a.d[i] - b.d[i];
}
num.len++;
}
//如果有前导0
while(num.d[num.len-1] == 0 && num.len!=1){
num.len--;
}
return num;
}
//比较函数
bool cmp(bign a,bign b){
//如果a的长度大于b那么返回true
if(a.len > b.len){
return true;
}else if(a.len < b.len){
return false;
}else{
//两者长度相等
for(int i=a.len-1;i>=0;i--){
if(a.d[i] > b.d[i]){
return true;
}else if(a.d[i] < b.d[i]){
return false;
}
}
}
//相等判做true
return false;
}
int main(){
scanf("%d",&t);
int cnt = 1;
while(t--){
//首先读取数据,char数组是以空格为结束符的
scanf("%s %s %s",A,B,C);
//接下来转换成bign结构体
bign a = change(A);
bign b = change(B);
bign c = change(C);
if(c.len == 1 && c.d[0] == 0){
c.flag = false;
}
bign res;
//接下来进行加减运算
if(a.flag && b.flag){
//两者都是正数
//直接相加
res = sum(a,b);
}else if(!a.flag && !b.flag){
//两者都是负数
//直接相加,再加负号
res = sum(a,b);
res.flag = false;
}else if(a.flag && !b.flag){
//A为正数,B为负数
//如果A的绝对值大于等于B的绝对值
//那么执行A-(-B)
if(cmp(a,b)){
res = sub(a,b);
}else{
res = sub(b,a);
res.flag = false;
}
}else if(!a.flag && b.flag){
//A为负数,B为正数
if(cmp(b,a)){
res = sub(b,a);
}else{
res = sub(a,b);
res.flag = false;
}
}
bool flag;
//之后再与c进行比较
if(res.flag && c.flag){
//两者为正数
if(cmp(res,c)){
flag = true;
}else{
flag = false;
}
}else if(!res.flag && !c.flag){
if(cmp(res,c)){
flag = false;
}else{
flag = true;
}
}else if(res.flag && !c.flag){
flag = true;
}else if(!res.flag && c.flag){
flag = false;
}
if(c.len == 1 && c.d[0] == 0 && res.len == 1 && res.d[0] == 0){
flag = false;
}
if(flag){
printf("Case #%d: true\n",cnt);
}else{
printf("Case #%d: false\n",cnt);
}
cnt++;
}
return 0;
}
码后反思
-
《算法笔记》上给出了一种不需要使用高精度整数就能计算的方法。很有巧妙性:
代码:#include<stdio.h> int main(){ int n; scanf("%d",&n); for(int i=0;i<n;i++){ long long a,b,c; scanf("%lld %lld %lld",&a,&b,&c); long long res = a+b; if( (a>0) && (b>0) && (res<0)){ printf("Case #%d: true\n",i+1); } else if( (a<0) && (b<0) && (res>=0)){ printf("Case #%d: false\n",i+1); } else if( (res) > c){ printf("Case #%d: true\n",i+1); }else{ printf("Case #%d: false\n",i+1); } } return 0; }
-
所谓的溢出范围的计算,可以通过数个数来进行;
-
注意
int
的范围是[ − 2 31 -2^{31} −231~ 2 31 − 1 2^{31}-1 231−1],long long
的范围是[ − 2 63 -2^{63} −263~ 2 63 − 1 2^{63}-1 263−1]
二刷代码
二刷之后,虽然自己知道要用溢出思考问题,但是还是没有考虑清楚溢出的种种情况,首先我居然还是忘记了int
和long long
的数值范围为:[
−
2
31
-2^{31}
−231~
2
31
−
1
2^{31}-1
231−1] 和 [
−
2
63
-2^{63}
−263~
2
63
−
1
2^{63}-1
263−1]。罪过罪过啊,之后的话没有思考到两个负数相加是可以 等于 0这种情况,导致测试点2没有过。
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
int main(){
ll a,b,c;
ll res;
int t;
scanf("%d",&t);
for(int i=1;i<=t;i++){
scanf("%lld %lld %lld",&a,&b,&c);
res=a+b;
if(a>0&&b>0&&res<0){
printf("Case #%d: true\n",i);
}else if(a<0&&b<0&&res>=0){
printf("Case #%d: false\n",i);
}else{
if(res>c){
printf("Case #%d: true\n",i);
}else{
printf("Case #%d: false\n",i);
}
}
}
return 0;
}