【题目描述】
Jzabc对多米诺骨牌有很大的兴趣,然而他的骨牌比较特别,只有黑的和白的。他觉得如果存在连续三个骨牌是同种颜色的,那这个骨牌排列就是不美观的。现在他有N个骨牌要排列,他想知道不美观的排列的个数。他想请你帮忙进行统计不美观排列的个数。
【输入格式】
只有一个正整数,即要排列的骨牌的个数。
【输出格式】
一个数,即不美观的排列的个数。
【输入样例】
4
【输出样例】
6
解释:有6中不美观的排列。
【数据规模】
对于20%的数据,满足N<=60
对于50%的数据,满足N<=600
对于100%的数据,满足N<=10000
【分析】
通过枚举可以发现有类似于斐波那契数列的规律。
递推加高精解决。
(简单的证明:)
每一个状态都有前面的状态推来。
如图
以i,j,k为例,i,j是前面的牌,k是等待加的牌。
那么k有两种加法。
1、如果k与j颜色不同,那么一定是美观的排列,直接把j的美观排列的个数加在k上。
2、如果k与j颜色相同,
(1)当j与i颜色不同。则k与j是等价的,即加上与j相同的k后,美观的数目没有增加。仍等于j的数目,而j等于什么呢?等于i。所以加上i中美观的数目。
(2)当i与j颜色相同。排列是不美观的,不考虑。
所以得出递推式:f[i]=f[i-1]+f[i-2];
【代码】
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define mo 100000000
using namespace std;
int tol,n;
struct node
{
int a[1010];
}f[20010];
int st[1010];
void jia(int n1,int n2)
{
for (int i=1;i<=1009;i++)
{
f[n1].a[i]+=f[n2].a[i];
if (f[n1].a[i]>=mo)
{
f[n1].a[i+1]+=(f[n1].a[i]/mo);
f[n1].a[i]%=mo;
}
}
}
void cheng(int n)
{
int hu[1010];
st[1]=1;
for(int i=1;i<=n;i++)
{
memset(hu,0,sizeof(hu));
for (int j=1;j<=1009;j++)
{
st[j]*=2;
st[j]+=hu[j];
if (st[j]>=mo)
{
hu[j+1]+=(st[j]/mo);
st[j]%=mo;
}
}
}
return ;
}
void jian()
{
for (int i=1;i<=1009;i++)
{
st[i]-=f[n].a[i];
if (st[i]<0)
{
st[i]+=mo;
st[i+1]--;
}
}
return;
}
int main()
{
freopen("domino.in","r",stdin);
freopen("domino.out","w",stdout);
scanf("%d",&n);
cheng(n);
f[1].a[1]=2;
f[2].a[1]=4;
for (int i=3;i<=n;i++)
{
jia(i,i-1);
jia(i,i-2);
}
jian();
int ii=1009;while (st[ii]==0) ii--;
cout<<st[ii]; ii--;
for (int i=ii;i>=1;i--) printf("%.8d",st[i]);
return 0;
}