hihocoder 1162 : 骨牌覆盖问题·三

来源:互联网 发布:软件个人外包 编辑:程序博客网 时间:2024/05/16 19:51

点击打开链接


描述

前两周里,我们讲解了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<stdio.h>#include<stdlib.h>#include<iostream>#include<math.h>#include<vector>#include<string>#include<sstream>#include<algorithm>#include<stack>#include<queue>#include<limits.h>#include<numeric>#include<cstring>#include<map>using namespace std;#define eps 1e-8#define LL long longconst LL mod=12357;const int MIN= -1e3;const int MAX= 128 ;const int MAX_N = 1e5 + 10;const int MAX_M = 1e5 + 10;const int MAX_K = 1e4+10;static LL N, M, K, T;struct matrlc {LL mapp[MAX][MAX];}ans, base;matrlc mult(matrlc a, matrlc b){matrlc c;for(int i=0; i<MAX; ++i){for(int j=0; j<MAX; ++j){c.mapp[i][j] = 0;for(int k=0; k<MAX; ++k){c.mapp[i][j] = (c.mapp[i][j] + (a.mapp[i][k] * b.mapp[k][j])%mod) %mod;}c.mapp[i][j] %=mod;}}return c;}void dfs(int l, int c, int p, matrlc& a){if(l > M) return;if(l == M) {a.mapp[p][c] = 1;return;}dfs(l+1, c<<1, (p<<1) +1, a);dfs(l+1, (c<<1) +1, p<<1, a);if((l+2)<=M){dfs(l+2, (c<<2)+3, (p<<2)+3, a);}}LL pow(LL n){memset(ans.mapp, 0, sizeof(ans.mapp));memset(base.mapp, 0, sizeof(base.mapp));for(int i=0;i<MAX; ++i) {ans.mapp[i][i] = 1;}dfs(0,0,0,base);while(n){if(n&1) {ans =mult(ans, base);}base = mult(base, base);n>>=1;}return ans.mapp[(1<<M)-1][(1<<M)-1]%mod;}int main () {scanf("%lld %lld", &M, &N);cout << pow(N) << endl;system("pause");return 0;}

分析:

题目简介里列数 应该改为 行数 从1> k开始循环

模拟骨牌放置,有三个规则,如提示所说。

所计算的是用任意状态x 能否转到y,DFS搜索所有X-》Y的情况,然后用快速幂算法 矩阵连成得出。

若矩阵太大的时候,则需要采用只表示矩阵边的办法

0 0
原创粉丝点击