我们知道邻接矩阵的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; }