hihocoder 1162 : 骨牌覆盖问题·三(四十三周)

方块问题的 最终形式 利用二进制进行状态转移,然后矩阵快速幂,[x][y] x为i-1列的状态,y为 i列状态, [x][y]能唯一标示所有的状态。

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

描述

前两周里,我们讲解了2xN,3xN骨牌覆盖的问题,并且引入了两种不同的递推方法。
这一次我们再加强一次题目,对于给定的K和N,我们需要去求KxN棋盘的覆盖方案数。

提示: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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值