版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/C_13579/article/details/82972785
地址:https://www.nowcoder.com/acm/contest/190/J
思路:状态压缩+矩阵快速幂
对于状态压缩方程易得转换方程
for(int i=2;i<=n;++i)
for(int j=0;j<=s;++j)
for(int k=0;k<=s;++k)
if((j||k)&&!(j&k)) dp[i][j]=(dp[i][j]+dp[i-1][k])%MOD;
而对于转移方程可以用矩阵快速幂来优化,与骨牌覆盖类似https://blog.csdn.net/C_13579/article/details/82883625
Code :
#include<iostream>
#include<cstring>
using namespace std;
typedef long long LL;
const int MOD=1e9+7;
const int MAX_S=35;
struct Matrix{
LL a[MAX_S][MAX_S];
Matrix(){memset(a,0,sizeof(a));}
Matrix operator*(const Matrix &A){
Matrix res=Matrix();
for(int k=0;k<MAX_S;++k)
for(int i=0;i<MAX_S;++i)
for(int j=0;j<MAX_S;++j)
res.a[i][j]=(res.a[i][j]+a[i][k]*A.a[k][j]%MOD)%MOD;
return res;
}
};
LL n,m;
int main()
{
ios::sync_with_stdio(false);
while(cin>>m>>n){
int s=(1<<m)-1;
Matrix t0=Matrix(),ans=Matrix();
for(int i=0;i<MAX_S;++i)
ans.a[i][i]=1;
for(int i=0;i<=s;++i)
for(int j=0;j<=s;++j)
if((i||j)&&!(i&j)) t0.a[i][j]=1;
--n;
while(n){
if(n&1) ans=ans*t0;
t0=t0*t0;
n>>=1;
}
LL res=0;
for(int i=0;i<=s;++i)
for(int j=0;j<=s;++j)
res=(res+ans.a[i][j])%MOD;
cout<<res<<endl;
}
return 0;
}