骨牌覆盖
P2070 - 骨牌覆盖
Description
有一个3*n的棋盘让你放入若干1*2的骨牌,要求将整棋盘恰好覆盖满。求方案数!
Input
一个整数n。
Output
方案数模12357的值。
Sample Input
2
Sample Output
3
Hint
1<=n<=100000000
打了个搜索找规律,结果8就跑不出来了QAQ,所以蒯了别人的代码看了看8是多少,
然后找出了递推式:f[i]=f[i-2]*4-f[i-4],f[0]=1,f[2]=3,f[奇数]=0
然后就可以矩阵快速幂啦。
初始矩阵:
a0 |
a1 |
0 |
0 |
递推矩阵:
0 |
-1 |
1 |
4 |
1 #include<set> 2 #include<map> 3 #include<queue> 4 #include<stack> 5 #include<ctime> 6 #include<cmath> 7 #include<string> 8 #include<vector> 9 #include<cstdio> 10 #include<cstdlib> 11 #include<cstring> 12 #include<iostream> 13 #include<algorithm> 14 #define mod 12357 15 #define LL long long 16 using namespace std; 17 LL a[2][2][2],s[2][2]; 18 int n; 19 void cale(int a1,int b1){ 20 for(int i=0;i<2;i++) 21 for(int j=0;j<2;j++) 22 for(int k=0;k<2;k++) 23 s[i][j]=(s[i][j]+a[a1][i][k]*a[b1][k][j])%mod; 24 for(int i=0;i<2;i++) 25 for(int j=0;j<2;j++) 26 a[a1][i][j]=s[i][j],s[i][j]=0; 27 } 28 void qpow(int n){ 29 while(n){ 30 if(n&1) cale(0,1); 31 n>>=1; 32 cale(1,1); 33 } 34 } 35 int main() 36 { 37 freopen("!.in","r",stdin); 38 freopen("!.out","w",stdout); 39 scanf("%d",&n); 40 if(n%2) {printf("0");return 0;} 41 if(n==0){printf("1");return 0;} 42 n=n/2; 43 a[0][0][0]=1,a[0][0][1]=3; 44 a[1][0][1]=-1,a[1][1][0]=1,a[1][1][1]=4; 45 qpow(n); 46 printf("%lld",a[0][0][0]%mod); 47 return 0; 48 }