模拟与高精度

高精度的实现其实很简单,用一个数组来存储一个数,数字123可以用数组{1, 2, 3}来存储(也可以逆序存储)。
最后用小学老师教过的方法来实现加减乘除即可。

不过最重要的是搞清楚四则运算的底层逻辑

例题1:乒乓球

国际乒联现在主席沙拉拉自从上任以来就立志于推行一系列改革,以推动乒乓球运动在全球的普及。

其中11分制改革引起了很大的争议,有一部分球员因为无法适应新规则只能选择退役。

华华就是其中一位,他退役之后走上了乒乓球研究工作,意图弄明白11分制和21分制对选手的不同影响。

在开展他的研究之前,他首先需要对他多年比赛的统计数据进行一些分析,所以需要你的帮忙。

华华通过以下方式进行分析,首先将比赛每个球的胜负列成一张表,然后分别计算在11分制和21分制下,双方的比赛结果(截至记录末尾)。 

比如现在有这么一份记录,(其中W表示华华获得一分,L表示华华对手获得一分): 

WWWWWWWWWWWWWWWWWWWWWWLW 

在11分制下,此时比赛的结果是华华第一局11比0获胜,第二局11比0获胜,正在进行第三局,当前比分1比1。

而在21分制下,此时比赛结果是华华第一局21比0获胜,正在进行第二局,比分2比1。

如果一局比赛刚开始,则此时比分为0比0。 

你的程序就是要对于一系列比赛信息的输入(WL形式),输出正确的结果。

输入格式:

每个输入文件包含若干行字符串(每行至多20个字母),字符串由大写的W、L和E组成。

其中E表示比赛信息结束,程序应该忽略E之后的所有内容。

输出格式:

输出由两部分组成,每部分有若干行,每一行对应一局比赛的比分(按比赛信息输入顺序)。

其中第一部分是11分制下的结果,第二部分是21分制下的结果,两部分之间由一个空行分隔。

输入样例:

WWWWWWWWWWWWWWWWWWWW
WWLWE

输出样例:

11:0
11:0
1:1

21:0
2:1

注意乒乓球的判分标准即可 ,如11分制下,在达到11分的同时,两队的分差还需要大于等于2,否则继续比赛,直到分差大于2

#include<bits/stdc++.h>
using namespace std;
struct race {
    int w, l;
};                //w,l分别表示华华和对手的得分
race race11[1000];//11分制的比赛
race race21[1000];//21分制的比赛
int main() {
    char ch;
    cin >> ch;
    int w11 = 0, w21 = 0, l11 = 0, l21 = 0, i = 0, j = 0;//i,j分别用来表示11分,21分制下的比赛局数
    while (ch != 'E') {//结束字符判断
        if (ch == 'W') {//华华得分了
            w11++;
            w21++;
        }
        if (ch == 'L') {//对手得分了
            l11++;
            l21++;
        }
        if ((w11== 11&&(w11-l11>=2))||(l11==11&&(l11-w11>=2))||((w11>11||l11>11)&&abs(w11-l11)>=2)){//华华赢得比赛,计分数据清0开始下一局
            race11[i].w = w11;
            race11[i].l = l11;
            w11 = 0, l11 = 0;
            i++;//比赛局数加1
        }
        if ((w21==21&&(w21-l21>=2))||(l21==21)&&(l21-w21>=2)||((w21 > 21 || l21 > 21) && abs(w21 - l21) >= 2)) {
            race21[j].w = w21;
            race21[j].l = l21;
            w21 = 0, l21 = 0;
            j++;
        }
        cin >> ch;
    }
    if (w11 != 0||l11!=0) {//正在进行的比赛的比分
        race11[i].w = w11;
        race11[i].l = l11;
        i++;
    }
    if (w21 != 0||l21!=0) {
        race21[j].w = w21;
        race21[j].l = l21;
        j++;
    }
    for (int k = 0; k < i; k++)printf("%d:%d\n", race11[k].w, race11[k].l);
    printf("\n");
    for (int m = 0; m < j; m++)printf("%d:%d\n", race21[m].w, race21[m].l);
    return 0;
}

 第二题:高精度加法

对于输入的两个不超过100位数字的非负整数,给出两数之和。

输入格式:

在两行中分别给出两个不超过100位数字的非负整数

输出格式:

在一行中输出两数之和

输入样例:

123
12

输出样例:

135

注意下标的起始别写错,解法可参考如下【模板+详解】 高精度加法 - dfydn - 博客园 (cnblogs.com)https://www.cnblogs.com/New-ljx/p/10480192.html

#include<bits/stdc++.h>
using namespace std;
int a[103], b[103], lena, lenb, t;//t存储进位
int main() {
    string sa, sb;
    cin >> sa >> sb;
    lena = sa.length();
    lenb = sb.length();
    for (int i = 0; i < lena; i++)//用数组a、b将读入的数据转换为逻辑上从小到大的存储
    {
        a[lena - 1 - i] = sa[i] - '0';//(len-1)-i
    }
    for (int i = 0; i < lenb; i++)
    {
        b[lenb - 1 - i] = sb[i] - '0';
    }
    if (lena >= lenb) {//将长度大的数字作为第一个乘数,方便进位计算
        for (int i = 0; i < lena; i++)
        {
            int temp = a[i];
            a[i] = (a[i] + b[i] + t) % 10;//十字相乘原理
            t = (temp + b[i] + t) / 10;//进位了
        }
        if (t)a[lena] = t;//还有多余的进位,数组长度加1(lena-1+1);
        else lena--;//a的下标是从0开始的,所以若没有进位则保持原有长度(lena-1)
        for (int j = lena; j >= 0; j--)
            cout << a[j];
    }
    else if (lena < lenb)
    {
        for (int i = 0; i < lenb; i++)
        {
            int temp = b[i];
            b[i] = (a[i] + b[i] + t) % 10;
            t = (temp + a[i] + t) / 10;
        }
        if (t)b[lenb] = t;
        else lenb--;
        for (int j = lenb; j >= 0; j--)
            cout << b[j];
    }

    return 0;
}

第三题:高精度求累加和

使用求和公式求1到N的累加和大家都会,但是如果把N值变大呢,比如100位的整数,那该怎么求?

输入格式:

输入在一行中给出1个位数不超过100位的整数N。

输出格式:

对每一组输入,在一行中输出1+2+3+……+N的值。

输入样例:

在这里给出一组输入。例如:

10

输出样例:

在这里给出相应的输出。例如:

55

利用高斯公式n个累加和等于(n+1)*n/2

其他高精度如求阶乘可参考以加深理解

【C语言高精度计算】—— n的阶乘 | 求a/b的高精度值 | n的累加和 | 阶乘和 | 高精度求积 - -Olivia- - 博客园

#include<bits/stdc++.h>
using namespace std;
int a[10000], b[10000],c[10000], lena, lenb, lenc,t;
int main(){
    string ch,sh;cin>>ch;
    sh=ch;
    lena=ch.length();
    lenb=sh.length();
    for(int i=0;i<lena;i++){//用数组a、b将读入的数据转换为逻辑上从小到大的存储
        a[lena-i]=ch[i]-'0';
        b[lenb-i]=sh[i]-'0';
    }
    b[1]++;//n+1
    for(int i=1;i<lenb;i++){//处理加1后产生的进位
        if(b[i]>=10){
            b[i]=0;
            b[i+1]++;
        }
        else break;
    }
    for(int i=1;i<=lenb;i++){//lenb>=lena,用b数组做为第一个乘数可以方便计算
        int x=0;//x存储进位
        for(int j=1;j<=lena;j++){
            c[i+j-1]=b[i]*a[j]+x+c[i+j-1];//i是起始下标,j-1是偏移的下标:a*b+进位+原数
            x=c[i+j-1]/10;//这是四则乘法运算的逻辑,可以自己在草稿纸上写一遍乘法运算理解
            c[i+j-1]%=10;
        }
        c[i+lena]=x;//进位
    }
    lenc=lena+lenb;//c数组的最长长度为lena+lenb
    for(int i=lenc;i>=1;i--){//(n+1)*n/2
        if(c[i]%2==0)c[i]/=2;
        else {
            c[i]/=2;
            c[i-1]+=10;//十进制下,余数1移到下一位变为10
        }
    }
    while(c[lenc]==0&&lenc>1)lenc--;//去除多余的0
    for(int i=lenc;i>=1;i--)cout<<c[i];
    cout<<endl;
    return 0;
}

两位数的乘积(附)

输入两个高精度正整数M和N(M和N均小于100位)。 求这两个高精度数的积。

输入样例:

  36 3

输出样例:

  108

#include<bits/stdc++.h>
using namespace std;
string s1, s2;
int a[1000], b[1000],c[2000],t;
int lena, lenb,lenc;
int main() {
    cin >> s1 >> s2;
    lena = s1.length();
    lenb = s2.length();
    for (int i = 1; i <= lena; i++) {
        a[i] = s1[lena-i]-'0';//下标从1开始
    }
    for (int i = 1; i <= lenb; i++) {
        b[i] = s2[lenb-i]-'0';
    }
    for (int i = 1; i <= lenb; i++)//123
    {
        t = 0;//t用于存放进位
        for (int j = 1; j <= lena; j++)//123456
        {
            c[i + j - 1] = a[j] * b[i] + t + c[i + j - 1];//i+(j-1)(当前乘积+上次乘积进位+原数)
            t = c[i + j - 1] / 10;
            c[i + j - 1] %= 10;
        }
        c[i + lena] = t;//有进位就加上
    }
    lenc = lena + lenb;
    while ((c[lenc] == 0) && (lenc > 1))//删除前导0,加上lenc>0的判断是防止乘积为0时无输出
        lenc--;
    for (int i = lenc; i >= 1; i--)//从最大位开始输出
    {
        cout << c[i];
    }
    cout << endl;
    return 0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值