HDUOJ1297/1002(大数计算)

ACM1297

第一次做这道题的时候,以为就是一个简单的递推题,但还是too native,结果自然是WA,后来测试发现题目给的范围是1~1000,但是取100数据就会溢出(即便使用的是long long),因此需要使用大数计算

先简单的分析这题的递推公式:用f(n)表示排队种类,假定已知f(n-1)
第n个是男生,则有f(n-1)种可能
第n个是女生,首先需要明确要使f(n)要合法,那么第n-1个必须为女生,接着需要分类讨论,如果前n-2个学生排列合法,则有f(n-2)种可能,如果前n-2个学生不合法,即第n-2是女生,第n-3是男生,此时再加上两个女生,队列就变成合法,因此这种情况有f(n-4)种可能
该题递推公式为f(n)=f(n-1)+f(n-2)+f(n-4)

接着需要解决大数计算的问题,接下来再引入ACM1002
大数计算基本思路:利用字符数组来保存每一位上的数字,并模拟手算

先讲解大数计算的核心代码

定义两个数组,用来存储需要相加的两个数

#define MAXN 10005 //MAXN值为几,就说明至少可以用来计算几位数之和
int list1[MAXN],list[MAXN];

程序做循环相加的时候要知道什么时候退出,因此需要知道较长的字符串长度,作为退出标志

int len1,len2,max_len;
len1=strlen(list1);
len2=strlen(list2);
max_len=max(len1,len2);

接下来我们要模拟手算

int temp=0//用来保存临时结算结果
for(int i=max_len;i>=1;i--)    //从最低位开始
{
    temp=list1[i]+list2[i]+temp;
    list1[i]+=temp%10;
    temp/=10;
}   

贴上杭电ACM1002的代码

#include<iostream>
#define MAXN 1005
using namespace std;
void add(char num1[MAXN], char num2[MAXN])
{
    int temp1[MAXN] = { 0 };int temp2[MAXN] = { 0 };
    int len1 = 0;int len2 = 0;
    int i = 0, j = 0;
    int maxlen = 0;
    len1 = strlen(num1);
    len2 = strlen(num2);

    反转字符串,便于从低位到高位相加和最高位的进位导致和的位数增加
    for (i = len1 - 1; i >= 0; i--)
    {
        temp1[j++] = num1[i] - '0';
    }
    temp1[j] = '\0';
    j = 0;
    for (i = len2 - 1; i >= 0; i--)
    {
        temp2[j++] = num2[i] - '0';
    }

    //一位一位的加
    maxlen = (len1 > len2) ? len1 : len2;
    for (i = 0; i < maxlen; i++) {
        temp1[i] += temp2[i];
        if (temp1[i] >= 10) {
            temp1[i] -= 10;
            temp1[i + 1]++;
        }
    }
    for (i = maxlen - 1; i >= 0; i--)
        cout << temp1[i];
}
int main()
{
    char s1[MAXN]; char s2[MAXN];    
    /*gets_s(num1);
    gets_s(num2);*/
    int t;
    cin >> t;
    for (int j = 1; j <= t;j++) {
        cin >> s1 >>s2;
        cout << "Case " << j << ":" << endl;
        cout << s1 << " + " << s2<<" = ";
        add(s1, s2);
        cout << endl;
        if (j!= t) {
            cout << endl;
        }
    }
    //add(num1, num2);
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值