单点时限: 1.0 sec
内存限制: 512 MB
问题描述
CuberQQ 有若干 1×1,2×1, 4×1 的骨牌。他想要知道拼出一个 n×1 的图形有多少种不同的方案。
输入格式
输入一个整数 n,表示图形的长度。
输出格式
在一行输出一个整数,表示方案数。
样例:
input:
5
output:
10
input:
4
output:
6
input:
100
output:
1620185239269438747405058
问题分析:
提示:
注意点:从样例可以看出数据类型大整数,但我当时做题没仔细看,递归很基础不用怎么想,但注意时间,所以需要一个数组来存放,减少耗时
考察点:大整数,递归
代码解决部分:
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
typedef long long int lli;
typedef struct{int cnt,v[501],sign;}BIGINT;
BIGINT int2BIG(lli x) //int 转换成BIGINT
{
BIGINT R= {0,{0},1};
if(x<0){R.sign=-1;x=-x;}
do
{
R.v[R.cnt++]=x%10;
x/=10;
} while (x>0);
return R;
}
void BIGoutput(BIGINT x)
{
if(x.sign==-1) printf("-");
for(int i=x.cnt-1;i>=0;i--) printf("%d",x.v[i]);
}
int cmp(BIGINT s,BIGINT t)
{
int n =(s.cnt>t.cnt)?s.cnt:t.cnt;
for(int i=n-1;i>=0;i--)
{
if(*(s.v+i)>*(t.v+i)) return 1;
else if(*(s.v+i)<*(t.v+i)) return -1;
}
return 0;
}
void SUB(BIGINT* s,BIGINT* t,BIGINT* result)
{
int n=(s->cnt>t->cnt)?s->cnt:t->cnt;
result->cnt=n;
int carry=0,i;
for(i=0;i<n;i++)
{
if((*(s->v+i)+carry)<(*(t->v+i)))
{
*(result->v+i)=*(s->v+i)+10+carry-*(t->v+i);
carry=-1;
}
else {
*(result->v+i)=*(s->v+i)+carry-*(t->v+i);
carry=0;
}
}
for (int i=n-1;i>=0&&result->v[i]==0;i--) result->cnt--;
}
BIGINT BIGSUB (BIGINT s,BIGINT t)
{
BIGINT R={0,{0},1};
if (cmp(s,t)>=0)
{
R.sign=1;
SUB(&s,&t,&R);
}
else
{
R.sign=-1;
SUB(&t,&s,&R);
}
return R;
}
BIGINT BIGADD(BIGINT s,BIGINT t)
{
if(s.cnt==0) return t;
if(t.cnt==0) return s;
BIGINT R={0,{0},1};
if(s.sign*t.sign<0)
{
if(s.sign==-1) R=BIGSUB(t,s);
else R=BIGSUB(s,t);
}
else
{
R.sign =s.sign;
int i,carry=0;
for(i=0 ;i<s.cnt&&i<t.cnt;i++)
{
int temp = s.v[i]+t.v[i]+carry;
R.v[i]=temp%10;
carry=temp/10;
}
while(i<t.cnt)
{
int temp =t.v[i]+carry;
R.v[i++] =temp%10;
carry = temp/10;
}
while (i<s.cnt)
{
int temp =s.v[i]+carry;
R.v[i++]=temp%10;
carry = temp/10;
}
if(carry)
{
R.v[i++]=carry%10;
}
R.cnt=i;
}
return R;
}
BIGINT a[501]={0,{0},1};
BIGINT zero={0,{0},1};
BIGINT domino(lli n)
{
if(n==0) return a[0];
if(n==1) return a[1];
if(n==2) return a[2];
if(n==3) return a[3];
if(n==4) return a[4];
else
{
if(a[n].cnt!=0) return a[n];
else
{
BIGINT x=domino(n-1);
BIGINT y=domino(n-2);
BIGINT z=domino(n-4);
BIGINT result=BIGADD(x,y);
result=BIGADD(result,z);
a[n]=result;
return result;
}
}
}
int main()
{
lli n;scanf("%lld",&n);
a[0]=int2BIG(0);
a[1]=int2BIG(1);
a[2]=int2BIG(2);
a[3]=int2BIG(3);
a[4]=int2BIG(6);
BIGoutput(domino(n));
return 0;
}
解释: