(\)
(Description)
用(1 imes 2)的矩形和面积为(3)的(L)形去覆盖一个(2 imes N) 的矩形,求方案数对(10^4+7)取模后的结果。
允许用于覆盖的图形旋转。两个方案不同当且仅当覆盖后形成的边界线至少有一处不同。
- (Nin [1,10^{100000}])
(\)
(Solution)
神仙出题人神仙做法
设(f[i][0/1])表示当前处理到第 (i) 位,前面的列都已经填满,当前位置填满 (/) 剩一个没填的方案数。
转移分放什么讨论,注意横着并排两个长条的情况要直接计数,新放置一个 (L) 形有两种不同的方式:
[egin{align}f[i][0]=f[i-1][0]+f[i-1][1]+f[i-2][0]end{align}
]
[egin{align}f[i][1]=2 imes f[i-2][0]+f[i-1][1]end{align}
]
把下面的式子带入((3)),有
[egin{align}f[i][0]=f[i-1][0]+f[i-2][0]+f[i-2][1]+2 imes f[i-3][0]end{align}
]
然后再把((1))式中的(i-1)代入,有
[f[i][0]=2 imes f[i-1][0]+f[i-3][0]
]
于是可以矩阵快速幂了。复杂度( ext O(log (10^{100000}))),因为快速幂迭代的时候指数是(N)需要高精度所以会(T);
然后黑科技十进制快速幂:(A^N=A^{lfloorfrac{N}{10} floor}A^{N\%10}),显然指数部分就可以直接按照高精按位计算了。
还有神仙做法是找循环节,发现是模数(-1),打个表就好了......
(\)
(Code)
#include<cmath>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define R register
#define mod 10007
#define gc getchar
using namespace std;
inline int rd(){
int x=0; char c=gc();
while(!isdigit(c)) c=gc();
while(isdigit(c)){x=((x<<1)+(x<<3)+(c^48))%(mod-1);c=gc();}
return x;
}
int n,f[mod]={1,1,2};
int main(){
n=rd();
for(R int i=3;i<=n;++i) f[i]=((f[i-1]*2)+f[i-3])%mod;
printf("%d",f[n]);
return 0;
}