CCF-201409-5-拼图

题意:
求拼图的方案总数
题解:
状压DP+快速幂
代码如下:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MOD=1e9+7,maxn=1e15+5,maxm=(1<<7)+5;
ll n,m,maxState;
struct Matrix{
	ll mp[maxm][maxm];
    void init_one() {
        ll i,j;
        for (i=0;i<maxState;i++){
            for (j=0;j<maxState;j++){
                if(i==j)mp[i][j]=1;
                else mp[i][j]=0;
            }
        }
    }
    friend Matrix operator*(Matrix a,Matrix b){
       Matrix res;
       int i,j,k;
       for (i=0;i<maxState;++i){
          for (j=0;j<maxState;++j){
             res.mp[i][j]=0;
             for (k=0;k<maxState;++k){
                res.mp[i][j]=(res.mp[i][j]+a.mp[i][k]*b.mp[k][j]%MOD)%MOD;
             }
          }
       }
       return res;
    }
    friend Matrix operator^(Matrix a,ll b){
		Matrix ans;
		ans.init_one();
		while(b){
			if(b&1)ans=ans*a;
			a=a*a;
			b>>=1;
		}
		return ans;
	}
};
Matrix a;
bool Empty(int i,int state){
    if(i<0||i>=m)return false;
    if((1<<i)&state)return false;
    return true;
}
void dfs(ll col,ll state,ll next){
    ll tmp;
    if(col==m){
        a.mp[state][next]++;
        a.mp[state][next]%=MOD;
        return;
    }
    if(!Empty(col,state))dfs(col+1,state,next);
    else{
        if((col-1>=0)&&Empty(col-1,next)&&Empty(col,next)){
          tmp=next;tmp|=(1<<col);tmp|=(1<<(col-1));
          dfs(col+1,state,tmp);
        }
        if((col+1<m)&&Empty(col,next)&&Empty(col+1,next)){
          tmp=next;tmp|=(1<<col);tmp|=(1<<(col+1));
          dfs(col+1,state,tmp);
        }
        if((col+1<m)&&Empty(col+1,state)&&Empty(col+1,next)){
          tmp=next;tmp|=(1<<(col+1));
          dfs(col+2,state,tmp);
        }
        if((col+1<m)&&Empty(col+1,state)&&Empty(col,next)){
           tmp=next;tmp|=(1<<col);
           dfs(col+2,state,tmp);
        }
    }
}
int main(){
    ll i,j;
    while(scanf("%lld%lld",&n,&m)!=EOF){
        maxState=(1<<m);
        memset(a.mp,0,sizeof(a.mp));
        for (i=0;i<maxState;i++)dfs(0,i,0);
        a=a^n;
        printf("%lld\n",a.mp[0][0]);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值