HDOJ1041 Computer Transformation 递推+大数

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1041

题目大意:定义这样的一个转换规则:0->1 0,1->0 1。初始只有一个数字1,按照转换规则,第一步之后数字变成01,第二步之后数字编程1001。。。以此类推。我们定义两个连续的0为一对0,求经过n步以后有多少个一对0。

首先需要明确永远不可能出现三个或以上的连续0。我们要求的就是经过n步以后有多少个一对0。列举所有数字可能的组合:00,01,10,11我们发现只有01下一步能够产生00,所以第n步00的个数=第n-1步01的个数。那么什么数字可以产生01呢?首先单独的1可以产生01,00也可以产生01。所以我们可以确定递推公式,设f[n].00为第n步以后00的个数,f[n].01为第n步以后01的个数,f[n].1为第n步以后1的个数,f[n].total为第n步以后总的数字个数,我们确定递推公式:

f[n].01=f[n-1].00+f[n-1].1
f[n].1=f[n-1].total
f[n].00=f[n-1].01
f[n].total=2*f[n-1].total

由于total以2的指数级增长,n最大到1000,所以如果用int或者long long来存储的话一定会溢出,所以这些成员需要用大整数来存储。

求解代码:

#include<cmath>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;

class BigInt{
private:
    string num;
public:
    BigInt(string s){
        for(string::iterator it=s.begin();it!=s.end();it++){
            string tmp_string(1,*it);
            num=tmp_string+num;
        }
    }
    BigInt(){}
    void multiply(int a,BigInt &b);//求乘积赋值给num
    void addBigInt(BigInt& a,BigInt &b);//求和赋值给num
    void output();
    string& getNum(){return num;}
    void setNum(string& s){
        num=s;
    }
};

void BigInt::output(){
    for(string::reverse_iterator it=num.rbegin();it!=num.rend();it++) printf("%c",*it);
    printf("\n");
}
void BigInt::multiply(int a,BigInt& b){
    num=b.num;

    int carry=0;
    int tmp;
    for(string::iterator iter=num.begin();iter!=num.end();iter++){
        tmp=((*iter)-'0')*a+carry;
        carry=tmp/10;
        *iter=tmp%10+'0';
    }
    while(carry!=0){
        tmp=carry%10;
        string tmp_string(1,tmp+'0');
        this->num=(this->num)+tmp_string;
        carry/=10;
    }
}
void BigInt::addBigInt(BigInt& a,BigInt& b){
    num=b.num;

    string& s=a.getNum();
    string::iterator it1=num.begin(),it2=s.begin();
    int carry=0;
    int tmp;
    while(it1!=num.end() && it2!=s.end()){
        tmp=(*it1-'0')+(*it2-'0')+carry;
        carry=tmp/10;
        *it1=tmp%10+'0';
        it1++;
        it2++;
    }
    while(it1!=num.end()){
        tmp=(*it1-'0')+carry;
        carry=tmp/10;
        *it1=tmp%10+'0';
        it1++;
    }
    while(it2!=s.end()){
        tmp=(*it2-'0')+carry;
        carry=tmp/10;
        string tmp_string(1,tmp%10+'0');
        num=num+tmp_string;
        it2++;
    }
    if(carry!=0){
        string tmp_string(1,carry+'0');
        num=num+tmp_string;
    }
}


struct Info{
    BigInt total;
    BigInt zero_one;
    BigInt one;
    BigInt zero_zero;
};
Info f[1005];
int main(){
    string tmp_string(1,'1');
    f[0].one.setNum(tmp_string);
    f[0].total.setNum(tmp_string);
    tmp_string="0";
    f[0].zero_one.setNum(tmp_string);
    f[0].zero_zero.setNum(tmp_string);
    for(int i=1;i<=1000;i++){
        f[i].zero_one.addBigInt(f[i-1].zero_zero,f[i-1].one);
        f[i].one.setNum(f[i-1].total.getNum());
        f[i].zero_zero.setNum(f[i-1].zero_one.getNum());
        f[i].total.multiply(2,f[i-1].total);
    }

/*
    cout<<"result:"<<endl;
    for(int i=1;i<=10;i++){
        cout<<"i="<<i<<endl;
        cout<<"01:";
        f[i].zero_one.output();
        cout<<"1:";
        f[i].one.output();
        cout<<"00:";
        f[i].zero_zero.output();
        cout<<"total:";
        f[i].total.output();

        cout<<endl;
    }
*/

    //f[1000].one.output();
    //f[1000].total.output();
    //f[1000].zero_one.output();
    //f[1000].zero_zero.output();
    int N;
    while(scanf("%d",&N)!=EOF){
        f[N].zero_zero.output();
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值