您的位置:首页 > 其它

hihoCoder #1162 : 骨牌覆盖问题·三

2015-10-08 21:07 267 查看

#1162 : 骨牌覆盖问题·三

Time Limit:10000ms
Case Time Limit:1000ms
Memory Limit:256MB

描述

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

提示:KxN骨牌覆盖

输入

第1行:2个整数N。表示棋盘宽度为k,长度为N。2≤K≤7,1≤N≤100,000,000

输出

第1行:1个整数,表示覆盖方案数 MOD 12357

Sample Input
2 62247088

Sample Output
1399

解题:dfs造转移方程+dp计数+快速幂优化dp


#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod = 12357;
int n,m;
struct Matrix{
int m[1<<7][1<<7];
Matrix(){
init();
}
void init(){
memset(m,0,sizeof m);
}
Matrix operator*(const Matrix &rhs){
Matrix ret;
for(int k = 0; k < (1<<n); ++k)
for(int i = 0; i < (1<<n); ++i)
for(int j = 0; j < (1<<n); ++j)
ret.m[i][j] = (ret.m[i][j] + m[i][k]*rhs.m[k][j])%mod;
return ret;
}
void print(){
for(int i = 0; i < 8; ++i){
for(int j = 0; j < 8; ++j)
printf("%d ",m[i][j]);
cout<<endl;
}
}
};
Matrix a,b;
void quickPow(LL index){
while(index){
if(index&1) a = a*b;
index >>= 1;
b = b*b;
}
}
bool tab[10][10];
void dfs(int cur,int st){
if(cur >= n){
int ss = 0;
for(int i = n-1; i >= 0; --i){
ss <<= 1;
ss |= tab[i][1];
}
b.m[st][ss]++;
return;
}
if(!tab[cur][0]){
if(!tab[cur][1]){
tab[cur][0] = tab[cur][1] = true;
dfs(cur+1,st);
tab[cur][0] = tab[cur][1] = false;
}
if(cur + 1 < n){
if(!tab[cur+1][0]){
tab[cur+1][0] = tab[cur][0] = true;
dfs(cur+2,st);
tab[cur+1][0] = tab[cur][0] = false;
}
}
}else dfs(cur + 1,st);
}
void init(int st){
memset(tab,false,sizeof tab);
for(int i = 0,xst = st; i < n; ++i,xst >>= 1)
tab[i][0] = xst&1;
dfs(0,st);
}
int main(){
while(~scanf("%d%d",&n,&m)){
b.init();
a.init();
for(int i = 0; i < (1<<n); ++i) init(i);
a.m[0][0] = 1;
quickPow(m);
printf("%d\n",a.m[0][0]);
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: