描述
今年的ACM暑期集训队一共有18人,分为6支队伍。其中有一个叫做YZJ的大佬,在共同的集训生活中,大家建立了深厚的友谊,YZJ准备做点什么来纪念这段激情燃烧的岁月,想了一想,YZJYZJ从家里拿来了一块上等的牛肉干,准备在上面刻下一个长度为nn的只由"Y" "Z" "J"三种字符组成的字符串(可以只有其中一种或两种字符,但绝对不能有其他字符),YZJ学长同时禁止在串中出现ZZ相邻的情况,他认为,"ZZ"看起来就像骂人的话语,影响不好。
你,NEW ACMer,YZJ的崇拜者,能帮学长算一下一共有多少种满足要求的不同的字符串吗?
输入
输入数据包含多个测试实例,每个测试实例占一行,由一个整数n组成,(0<n<40)。
输出
对于每个测试实例,请输出全部的满足要求的涂法,每个实例的输出占一行。
输入样例 1
1 2
输出样例 1
3 8
来源
hg
在牛肉干上面刻字,刻字的选择是Y,Z,J三个字符中的任意一个。
限制条件:Z和Z不能相连。
接下来,画图找规律:(图省略了~~~)
1 f[1]=3
2 f[2]=8
3 f[3]=22
4 f[4]=60
突然发现f[n]=2*(f[n-1]+f[n-2])。
#include<cstdio>
const int maxn=50;
long long a[maxn]={1,3};
int main()
{
int i,n;
for(i=2;i<40;i++)
{
a[i]=2*(a[i-1]+a[i-2]);
}
while(~scanf("%d",&n))
{
printf("%lld\n",a[n]);
}
return 0;
}
当然,如果说这道题的n的数据范围特别大的话,这样做肯定是不行的(爆数据范围),可以使用矩阵快速幂的方法来解决这个问题。
矩阵的构造:
现在是三个字符Y,Z,J,其中Z和Z不能相邻,那么所有的清苦应该有八种:
YY、YZ、YJ、ZY、ZJ、JY、JZ、JJ,将这八种情况用从0开始的数字表示,对应的数字分别为0、1、2、3、4、5、6、7.
对于YY来说,确定了第一个Y之后,它对后面的情况没有影响了,所以只需考虑后面的Y就行了,也就是YY,YZ,YJ这三种情况。
对应的数字分别为0,1,2.
同理找出其他的关系,然后构造矩阵:
代码如下:
#include<algorithm>
#include<iostream>
#include<string.h>
#include<cstdio>
#include<cstring>
#define P pair<long long,long long>
#define ms(a,b) memset(a,b,sizeof(a))
#define ll long long
using namespace std;
ll N,a,b,k;
struct xiao
{
ll f[8][8];
} ans,mapp;
void init(xiao &ans)
{
for(int i=0; i<8; ++i)
{
for(int j=0; j<8; ++j)
{
if(i==j)
ans.f[i][j]=1;
else
ans.f[i][j]=0;
}
}
}
void power(xiao &x,xiao &y,xiao &z)
{
ms(z.f,0);
for(int i=0; i<8; ++i)
{
for(int j=0; j<8; ++j)
{
if(x.f[i][j])
{
for(int k=0; k<8; ++k)
{
z.f[i][k]+=(x.f[i][j]*y.f[j][k]);
}
}
}
}
}
ll solve(ll k)
{
init(ans);
ll number=k;
xiao temp=mapp,t;
while(number)
{
if(number%2==1)
{
power(ans,temp,t);
ans=t;
}
power(temp,temp,t);
temp=t;
number/=2;
}
return ans.f[0][0]+ans.f[0][1]+ans.f[0][2]+ans.f[0][3]+ans.f[0][4]+ans.f[0][5]+ans.f[0][6]+ans.f[0][7];
}
int main()
{
ll n;
mapp=
{
1,1,1,0,0,0,0,0,
0,0,0,1,1,0,0,0,
0,0,0,0,0,1,1,1,
1,1,1,0,0,0,0,0,
0,0,0,0,0,1,1,1,
1,1,1,0,0,0,0,0,
0,0,0,1,1,0,0,0,
0,0,0,0,0,1,1,1
};
xiao t,x;
power(mapp,mapp,t);
while(cin>>n)
{
printf("%lld\n",solve(n));
}
return 0;
}