题目链接: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();
}
}