方块问题的 最终形式 利用二进制进行状态转移,然后矩阵快速幂,[x][y] x为i-1列的状态,y为 i列状态, [x][y]能唯一标示所有的状态。
时间限制:10000ms
单点时限:1000ms
内存限制:256MB
描述
前两周里,我们讲解了2xN,3xN骨牌覆盖的问题,并且引入了两种不同的递推方法。
这一次我们再加强一次题目,对于给定的K和N,我们需要去求KxN棋盘的覆盖方案数。
输入
第1行:2个整数N。表示棋盘宽度为k,长度为N。2≤K≤7,1≤N≤100,000,000
输出
第1行:1个整数,表示覆盖方案数 MOD 12357
样例输入
2 62247088
样例输出
1399
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define ff(i,a,b) for(int i = a; i <= b; i++)
#define f(i,a,b) for(int i = a; i < b; i++)
typedef pair<int,int> P;
#define ll long long
const int MOD = 12357;
const int M = 1<<7;
int a[M][M],b[M][M],c[M][M];
int k,n,m;
void dfs(int l, int c, int p)
{
if(l > k) return ;
if(l == k)
{
a[p][c]++;
return ;
}
dfs(l + 2, c << 2| 3, p << 2|3);
dfs(l + 1, c << 1| 1, p << 1);
dfs(l+1,c<<1,p << 1|1);
}
void mul(int x[M][M],int y[M][M])
{
memset(c,0,sizeof(c));
f(i,0,m) f(j,0,m) f(t,0,m){
c[i][j] += x[i][t] * y[t][j];
if(c[i][j] >= MOD) c[i][j] %= MOD;
}
memcpy(x,c,sizeof(c));
}
int main()
{
ios::sync_with_stdio(false);
cin >> k >> n;
m = 1 << k;
if((n*k) %2 == 1) cout << 0 << endl;
else
{
dfs(0,0,0);
f(i,0,m) b[i][i] = 1;
while(n)
{
if(n & 1) mul(b,a);
mul(a,a);
n >>= 1;
}
printf("%d\n",b[m - 1][m - 1] );
}
return 0;
}