HDUOJ1297/1002(大数计算)

来源:互联网 发布:中信建投证券软件 编辑:程序博客网 时间:2024/06/03 13:19

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 1005using 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;}