我们知道邻接矩阵的k次方就是一个从i到j之间允许重复路径的条数
然后我们对于这题我们也可以向着这个方向转化
先用dfs搜索出所有的状态转移,然后把每一个状态当成一个点,就变成上面的问题了
当然最极端的方法自然是推递推公式或者通项公式啦
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<bitset>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define down(i,a,b) for(int i=a;u>=b;i--)
using namespace std;
#define N 32
int n,m,nm,inf;
struct matrix
{
int a[N][N];
void clear()
{
memset(a,0,sizeof(a));
}
void OUT()
{
fo(i,0,m)
{
fo(j,0,m)
{
cout<<a[i][j]<<' ';
}cout<<endl;
}cout<<endl;
}
matrix operator*(const matrix b)const
{
matrix anss;
fo(i,0,m)
fo(j,0,m)
{
anss.a[i][j]=0;
fo(k,0,m)
{
anss.a[i][j]+=a[i][k]*b.a[k][j];
anss.a[i][j]%=inf;
}
}
return anss;
}
}I,A;
void getI()
{
fo(i,0,m)
fo(j,0,m)
if(i==j)I.a[i][j]=1;
else I.a[i][j]=0;
}
bitset<100>a;
bitset<100>pre;
void dfs(int k,unsigned long cnt,unsigned long now)
{
// cout<<k<<' '<<pre<<' '<<a<<endl;
if(k>nm)return;
A.a[cnt][now]=1;
if(!a[k-1]&&!a[k])
{
a[k]=1,a[k-1]=1;
dfs(k+1,cnt,a.to_ulong());
a[k]=0,a[k-1]=0;
}
dfs(k+1,cnt,now);
}
matrix KSM(matrix a,int k)
{
matrix ret=I;
while(k)
{
if(k&1)ret=a*ret;
a=a*a;
k>>=1;
}
return ret;
}
int main()
{
scanf("%d%d%d",&n,&nm,&inf);
m=(1<<nm)-1;A.clear();getI();
fo(i,0,m)
{
a.reset();pre=i;a=m-i;
dfs(1,i,m-i);
}
// A.OUT();
matrix ans=KSM(A,n);
cout<<ans.a[m][m]<<endl;
return 0;
}